<!DOCTYPE html>
<html lang="" xml:lang="">
<head>

  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <title>Chapter 15 Custom Outputs | JavaScript for R</title>
  <meta name="description" content="Invite JavaScript into your Data Science workflow." />
  <meta name="generator" content="bookdown 0.20 and GitBook 2.6.7" />

  <meta property="og:title" content="Chapter 15 Custom Outputs | JavaScript for R" />
  <meta property="og:type" content="book" />
  
  
  <meta property="og:description" content="Invite JavaScript into your Data Science workflow." />
  <meta name="github-repo" content="JohnCoene/javascript-for-r" />

  <meta name="twitter:card" content="summary" />
  <meta name="twitter:title" content="Chapter 15 Custom Outputs | JavaScript for R" />
  
  <meta name="twitter:description" content="Invite JavaScript into your Data Science workflow." />
  

<meta name="author" content="John Coene" />


<meta name="date" content="2020-09-04" />

  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="apple-mobile-web-app-capable" content="yes" />
  <meta name="apple-mobile-web-app-status-bar-style" content="black" />
  
  
<link rel="prev" href="tips-tricks.html"/>
<link rel="next" href="custom-inputs.html"/>
<script src="libs/header-attrs/header-attrs.js"></script>
<script src="libs/jquery/jquery.min.js"></script>
<link href="libs/gitbook/css/style.css" rel="stylesheet" />
<link href="libs/gitbook/css/plugin-table.css" rel="stylesheet" />
<link href="libs/gitbook/css/plugin-bookdown.css" rel="stylesheet" />
<link href="libs/gitbook/css/plugin-highlight.css" rel="stylesheet" />
<link href="libs/gitbook/css/plugin-search.css" rel="stylesheet" />
<link href="libs/gitbook/css/plugin-fontsettings.css" rel="stylesheet" />
<link href="libs/gitbook/css/plugin-clipboard.css" rel="stylesheet" />









<script src="libs/accessible-code-block/empty-anchor.js"></script>
<script src="libs/htmlwidgets/htmlwidgets.js"></script>
<script src="libs/plotly-binding/plotly.js"></script>
<script src="libs/typedarray/typedarray.min.js"></script>
<link href="libs/crosstalk/css/crosstalk.css" rel="stylesheet" />
<script src="libs/crosstalk/js/crosstalk.min.js"></script>
<link href="libs/plotly-htmlwidgets-css/plotly-htmlwidgets.css" rel="stylesheet" />
<script src="libs/plotly-main/plotly-latest.min.js"></script>
<script src="libs/core-js/shim.min.js"></script>
<script src="libs/react/react.min.js"></script>
<script src="libs/react/react-dom.min.js"></script>
<script src="libs/reactwidget/react-tools.js"></script>
<script src="libs/reactable-binding/reactable.js"></script>
<script src="libs/r2d3-render/r2d3-render.js"></script>
<script src="libs/webcomponents/webcomponents.js"></script>
<script src="libs/r2d3-binding/r2d3.js"></script>
<script src="libs/d3v5/d3.min.js"></script>
<script src="libs/viz/viz.js"></script>
<link href="libs/DiagrammeR-styles/styles.css" rel="stylesheet" />
<script src="libs/grViz-binding/grViz.js"></script>


<style type="text/css">
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
  { counter-reset: source-line 0; }
pre.numberSource code > span
  { position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
  { content: counter(source-line);
    position: relative; left: -1em; text-align: right; vertical-align: baseline;
    border: none; display: inline-block;
    -webkit-touch-callout: none; -webkit-user-select: none;
    -khtml-user-select: none; -moz-user-select: none;
    -ms-user-select: none; user-select: none;
    padding: 0 4px; width: 4em;
    color: #aaaaaa;
  }
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
div.sourceCode
  {   }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>

<link rel="stylesheet" href="css/style.css" type="text/css" />
<link rel="stylesheet" href="css/toc.css" type="text/css" />
</head>

<body>



  <div class="book without-animation with-summary font-size-2 font-family-1" data-basepath=".">

    <div class="book-summary">
      <nav role="navigation">

<ul class="summary">
<li><a href="./">JavaScript for R</a></li>

<li class="divider"></li>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>Preface</a>
<ul>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#premise"><i class="fa fa-check"></i>Premise</a></li>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#book-structure"><i class="fa fa-check"></i>Book Structure</a></li>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#acknowledgement"><i class="fa fa-check"></i>Acknowledgement</a></li>
</ul></li>
<li class="part"><span><b>I Basics &amp; Roadmap</b></span></li>
<li class="chapter" data-level="1" data-path="overview.html"><a href="overview.html"><i class="fa fa-check"></i><b>1</b> Overview</a>
<ul>
<li class="chapter" data-level="1.1" data-path="overview.html"><a href="overview.html#rationale"><i class="fa fa-check"></i><b>1.1</b> Rationale</a></li>
<li class="chapter" data-level="1.2" data-path="overview.html"><a href="overview.html#methods"><i class="fa fa-check"></i><b>1.2</b> Methods</a>
<ul>
<li class="chapter" data-level="1.2.1" data-path="overview.html"><a href="overview.html#v8"><i class="fa fa-check"></i><b>1.2.1</b> V8</a></li>
<li class="chapter" data-level="1.2.2" data-path="overview.html"><a href="overview.html#htmlwidgets"><i class="fa fa-check"></i><b>1.2.2</b> htmlwidgets</a></li>
<li class="chapter" data-level="1.2.3" data-path="overview.html"><a href="overview.html#shiny"><i class="fa fa-check"></i><b>1.2.3</b> Shiny</a></li>
<li class="chapter" data-level="1.2.4" data-path="overview.html"><a href="overview.html#bubble"><i class="fa fa-check"></i><b>1.2.4</b> bubble</a></li>
</ul></li>
<li class="chapter" data-level="1.3" data-path="overview.html"><a href="overview.html#methods-amiss"><i class="fa fa-check"></i><b>1.3</b> Methods Amiss</a>
<ul>
<li class="chapter" data-level="1.3.1" data-path="overview.html"><a href="overview.html#reactr"><i class="fa fa-check"></i><b>1.3.1</b> reactR</a></li>
<li class="chapter" data-level="1.3.2" data-path="overview.html"><a href="overview.html#r2d3"><i class="fa fa-check"></i><b>1.3.2</b> r2d3</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="2" data-path="prerequisites.html"><a href="prerequisites.html"><i class="fa fa-check"></i><b>2</b> Prerequisites</a>
<ul>
<li class="chapter" data-level="2.1" data-path="prerequisites.html"><a href="prerequisites.html#r-package-development"><i class="fa fa-check"></i><b>2.1</b> R Package Development</a>
<ul>
<li class="chapter" data-level="2.1.1" data-path="prerequisites.html"><a href="prerequisites.html#creating-a-package"><i class="fa fa-check"></i><b>2.1.1</b> Creating a Package</a></li>
<li class="chapter" data-level="2.1.2" data-path="prerequisites.html"><a href="prerequisites.html#metadata"><i class="fa fa-check"></i><b>2.1.2</b> Metadata</a></li>
<li class="chapter" data-level="2.1.3" data-path="prerequisites.html"><a href="prerequisites.html#r-code"><i class="fa fa-check"></i><b>2.1.3</b> R code</a></li>
<li class="chapter" data-level="2.1.4" data-path="prerequisites.html"><a href="prerequisites.html#documentation"><i class="fa fa-check"></i><b>2.1.4</b> Documentation</a></li>
<li class="chapter" data-level="2.1.5" data-path="prerequisites.html"><a href="prerequisites.html#installed-files"><i class="fa fa-check"></i><b>2.1.5</b> Installed files</a></li>
<li class="chapter" data-level="2.1.6" data-path="prerequisites.html"><a href="prerequisites.html#build-load-and-install"><i class="fa fa-check"></i><b>2.1.6</b> Build, load, and install</a></li>
</ul></li>
<li class="chapter" data-level="2.2" data-path="prerequisites.html"><a href="prerequisites.html#json"><i class="fa fa-check"></i><b>2.2</b> JSON</a>
<ul>
<li class="chapter" data-level="2.2.1" data-path="prerequisites.html"><a href="prerequisites.html#serialising"><i class="fa fa-check"></i><b>2.2.1</b> Serialising</a></li>
<li class="chapter" data-level="2.2.2" data-path="prerequisites.html"><a href="prerequisites.html#tabular-data"><i class="fa fa-check"></i><b>2.2.2</b> Tabular data</a></li>
</ul></li>
<li class="chapter" data-level="2.3" data-path="prerequisites.html"><a href="prerequisites.html#javascript"><i class="fa fa-check"></i><b>2.3</b> JavaScript</a>
<ul>
<li class="chapter" data-level="2.3.1" data-path="prerequisites.html"><a href="prerequisites.html#developer-tools"><i class="fa fa-check"></i><b>2.3.1</b> Developer tools</a></li>
<li class="chapter" data-level="2.3.2" data-path="prerequisites.html"><a href="prerequisites.html#variable-declaration-and-scope"><i class="fa fa-check"></i><b>2.3.2</b> Variable declaration and scope</a></li>
<li class="chapter" data-level="2.3.3" data-path="prerequisites.html"><a href="prerequisites.html#document-object-model"><i class="fa fa-check"></i><b>2.3.3</b> Document object model</a></li>
</ul></li>
<li class="chapter" data-level="2.4" data-path="overview.html"><a href="overview.html#shiny"><i class="fa fa-check"></i><b>2.4</b> Shiny</a>
<ul>
<li class="chapter" data-level="2.4.1" data-path="prerequisites.html"><a href="prerequisites.html#htmltools"><i class="fa fa-check"></i><b>2.4.1</b> Htmltools</a></li>
<li class="chapter" data-level="2.4.2" data-path="prerequisites.html"><a href="prerequisites.html#static-files"><i class="fa fa-check"></i><b>2.4.2</b> Static files</a></li>
<li class="chapter" data-level="2.4.3" data-path="prerequisites.html"><a href="prerequisites.html#dependencies-pros-and-cons"><i class="fa fa-check"></i><b>2.4.3</b> Dependencies Pros and Cons</a></li>
</ul></li>
</ul></li>
<li class="part"><span><b>II Data Visualisation</b></span></li>
<li class="chapter" data-level="3" data-path="introduction-to-widgets.html"><a href="introduction-to-widgets.html"><i class="fa fa-check"></i><b>3</b> Introduction to Widgets</a>
<ul>
<li class="chapter" data-level="3.1" data-path="introduction-to-widgets.html"><a href="introduction-to-widgets.html#plotly-package"><i class="fa fa-check"></i><b>3.1</b> Plotly package</a></li>
<li class="chapter" data-level="3.2" data-path="introduction-to-widgets.html"><a href="introduction-to-widgets.html#dt-package"><i class="fa fa-check"></i><b>3.2</b> DT package</a></li>
</ul></li>
<li class="chapter" data-level="4" data-path="basics-of-building-widgets.html"><a href="basics-of-building-widgets.html"><i class="fa fa-check"></i><b>4</b> Basics of Building Widgets</a>
<ul>
<li class="chapter" data-level="4.1" data-path="basics-of-building-widgets.html"><a href="basics-of-building-widgets.html#candidate-libraries"><i class="fa fa-check"></i><b>4.1</b> Candidate Libraries</a>
<ul>
<li class="chapter" data-level="4.1.1" data-path="basics-of-building-widgets.html"><a href="basics-of-building-widgets.html#plotly.js"><i class="fa fa-check"></i><b>4.1.1</b> Plotly.js</a></li>
<li class="chapter" data-level="4.1.2" data-path="basics-of-building-widgets.html"><a href="basics-of-building-widgets.html#highchart.js"><i class="fa fa-check"></i><b>4.1.2</b> Highchart.js</a></li>
<li class="chapter" data-level="4.1.3" data-path="basics-of-building-widgets.html"><a href="basics-of-building-widgets.html#chart.js"><i class="fa fa-check"></i><b>4.1.3</b> Chart.js</a></li>
</ul></li>
<li class="chapter" data-level="4.2" data-path="basics-of-building-widgets.html"><a href="basics-of-building-widgets.html#how-it-works"><i class="fa fa-check"></i><b>4.2</b> How it works</a></li>
</ul></li>
<li class="chapter" data-level="5" data-path="your-first-widget.html"><a href="your-first-widget.html"><i class="fa fa-check"></i><b>5</b> Your First Widget</a>
<ul>
<li class="chapter" data-level="5.1" data-path="your-first-widget.html"><a href="your-first-widget.html#the-htmlwidgets-scaffold"><i class="fa fa-check"></i><b>5.1</b> The Htmlwidgets Scaffold</a></li>
<li class="chapter" data-level="5.2" data-path="your-first-widget.html"><a href="your-first-widget.html#the-html-output"><i class="fa fa-check"></i><b>5.2</b> The HTML Output</a></li>
<li class="chapter" data-level="5.3" data-path="your-first-widget.html"><a href="your-first-widget.html#htmlwidgets-javascript-files"><i class="fa fa-check"></i><b>5.3</b> Htmlwidgets JavaScript Files</a></li>
</ul></li>
<li class="chapter" data-level="6" data-path="a-realistic-widget.html"><a href="a-realistic-widget.html"><i class="fa fa-check"></i><b>6</b> A Realistic Widget</a>
<ul>
<li class="chapter" data-level="6.1" data-path="a-realistic-widget.html"><a href="a-realistic-widget.html#peity.js-dependencies"><i class="fa fa-check"></i><b>6.1</b> Peity.js Dependencies</a></li>
<li class="chapter" data-level="6.2" data-path="a-realistic-widget.html"><a href="a-realistic-widget.html#peity.js-implementation"><i class="fa fa-check"></i><b>6.2</b> Peity.js Implementation</a></li>
<li class="chapter" data-level="6.3" data-path="a-realistic-widget.html"><a href="a-realistic-widget.html#peity.js-html-element"><i class="fa fa-check"></i><b>6.3</b> Peity.js HTML Element</a></li>
</ul></li>
<li class="chapter" data-level="7" data-path="the-full-monty.html"><a href="the-full-monty.html"><i class="fa fa-check"></i><b>7</b> The Full Monty</a>
<ul>
<li class="chapter" data-level="7.1" data-path="the-full-monty.html"><a href="the-full-monty.html#gio.js-dependencies"><i class="fa fa-check"></i><b>7.1</b> Gio.js Dependencies</a></li>
<li class="chapter" data-level="7.2" data-path="the-full-monty.html"><a href="the-full-monty.html#gio.js-javascript"><i class="fa fa-check"></i><b>7.2</b> Gio.js JavaScript</a></li>
<li class="chapter" data-level="7.3" data-path="the-full-monty.html"><a href="the-full-monty.html#working-with-data"><i class="fa fa-check"></i><b>7.3</b> Working with Data</a></li>
<li class="chapter" data-level="7.4" data-path="the-full-monty.html"><a href="the-full-monty.html#transforming-data"><i class="fa fa-check"></i><b>7.4</b> Transforming Data</a>
<ul>
<li class="chapter" data-level="7.4.1" data-path="the-full-monty.html"><a href="the-full-monty.html#using-javascript"><i class="fa fa-check"></i><b>7.4.1</b> Using JavaScript</a></li>
<li class="chapter" data-level="7.4.2" data-path="the-full-monty.html"><a href="the-full-monty.html#using-r"><i class="fa fa-check"></i><b>7.4.2</b> Using R</a></li>
<li class="chapter" data-level="7.4.3" data-path="the-full-monty.html"><a href="the-full-monty.html#pros-cons"><i class="fa fa-check"></i><b>7.4.3</b> Pros &amp; Cons</a></li>
</ul></li>
<li class="chapter" data-level="7.5" data-path="the-full-monty.html"><a href="the-full-monty.html#on-print-method"><i class="fa fa-check"></i><b>7.5</b> On Print Method</a></li>
</ul></li>
<li class="chapter" data-level="8" data-path="advanced-topics.html"><a href="advanced-topics.html"><i class="fa fa-check"></i><b>8</b> Advanced Topics</a>
<ul>
<li class="chapter" data-level="8.1" data-path="advanced-topics.html"><a href="advanced-topics.html#shared-variables"><i class="fa fa-check"></i><b>8.1</b> Shared Variables</a>
<ul>
<li class="chapter" data-level="8.1.1" data-path="advanced-topics.html"><a href="advanced-topics.html#sizing"><i class="fa fa-check"></i><b>8.1.1</b> Sizing</a></li>
<li class="chapter" data-level="8.1.2" data-path="advanced-topics.html"><a href="advanced-topics.html#sizing-policy"><i class="fa fa-check"></i><b>8.1.2</b> Sizing Policy</a></li>
</ul></li>
<li class="chapter" data-level="8.2" data-path="advanced-topics.html"><a href="advanced-topics.html#resizing"><i class="fa fa-check"></i><b>8.2</b> Resizing</a></li>
<li class="chapter" data-level="8.3" data-path="advanced-topics.html"><a href="advanced-topics.html#pre-render-hooks-security"><i class="fa fa-check"></i><b>8.3</b> Pre Render Hooks &amp; Security</a></li>
<li class="chapter" data-level="8.4" data-path="advanced-topics.html"><a href="advanced-topics.html#javascript-code"><i class="fa fa-check"></i><b>8.4</b> JavaScript Code</a></li>
<li class="chapter" data-level="8.5" data-path="advanced-topics.html"><a href="advanced-topics.html#prepend-append-content"><i class="fa fa-check"></i><b>8.5</b> Prepend &amp; Append Content</a></li>
<li class="chapter" data-level="8.6" data-path="advanced-topics.html"><a href="advanced-topics.html#dependencies"><i class="fa fa-check"></i><b>8.6</b> Dependencies</a></li>
<li class="chapter" data-level="8.7" data-path="advanced-topics.html"><a href="advanced-topics.html#compatibility"><i class="fa fa-check"></i><b>8.7</b> Compatibility</a></li>
<li class="chapter" data-level="8.8" data-path="advanced-topics.html"><a href="advanced-topics.html#unit-tests"><i class="fa fa-check"></i><b>8.8</b> Unit Tests</a></li>
<li class="chapter" data-level="8.9" data-path="advanced-topics.html"><a href="advanced-topics.html#performances"><i class="fa fa-check"></i><b>8.9</b> Performances</a></li>
</ul></li>
<li class="chapter" data-level="9" data-path="linking-widgets.html"><a href="linking-widgets.html"><i class="fa fa-check"></i><b>9</b> Linking Widgets</a>
<ul>
<li class="chapter" data-level="9.1" data-path="linking-widgets.html"><a href="linking-widgets.html#crosstalk-examples"><i class="fa fa-check"></i><b>9.1</b> Crosstalk examples</a></li>
<li class="chapter" data-level="9.2" data-path="linking-widgets.html"><a href="linking-widgets.html#crosstalk-requirements"><i class="fa fa-check"></i><b>9.2</b> Crosstalk requirements</a></li>
<li class="chapter" data-level="9.3" data-path="basics-of-building-widgets.html"><a href="basics-of-building-widgets.html#how-it-works"><i class="fa fa-check"></i><b>9.3</b> How it works</a></li>
<li class="chapter" data-level="9.4" data-path="linking-widgets.html"><a href="linking-widgets.html#crosstalk-with-gio"><i class="fa fa-check"></i><b>9.4</b> Crosstalk with gio</a></li>
<li class="chapter" data-level="9.5" data-path="linking-widgets.html"><a href="linking-widgets.html#adapt-the-r-code"><i class="fa fa-check"></i><b>9.5</b> Adapt the R code</a></li>
<li class="chapter" data-level="9.6" data-path="linking-widgets.html"><a href="linking-widgets.html#change-the-javascript-code"><i class="fa fa-check"></i><b>9.6</b> Change the JavaScript code</a>
<ul>
<li class="chapter" data-level="9.6.1" data-path="linking-widgets.html"><a href="linking-widgets.html#send-selected-keys"><i class="fa fa-check"></i><b>9.6.1</b> Send selected keys</a></li>
<li class="chapter" data-level="9.6.2" data-path="linking-widgets.html"><a href="linking-widgets.html#set-selected-keys"><i class="fa fa-check"></i><b>9.6.2</b> Set selected keys</a></li>
<li class="chapter" data-level="9.6.3" data-path="linking-widgets.html"><a href="linking-widgets.html#recap-javascript-code"><i class="fa fa-check"></i><b>9.6.3</b> Recap JavaScript code</a></li>
</ul></li>
<li class="chapter" data-level="9.7" data-path="linking-widgets.html"><a href="linking-widgets.html#using-crosstalk-with-gio"><i class="fa fa-check"></i><b>9.7</b> Using crosstalk with gio</a></li>
</ul></li>
<li class="chapter" data-level="10" data-path="final-revisions.html"><a href="final-revisions.html"><i class="fa fa-check"></i><b>10</b> Final Revisions</a>
<ul>
<li class="chapter" data-level="10.1" data-path="final-revisions.html"><a href="final-revisions.html#htmlwidgets-data"><i class="fa fa-check"></i><b>10.1</b> Htmlwidgets &amp; Data</a></li>
<li class="chapter" data-level="10.2" data-path="final-revisions.html"><a href="final-revisions.html#plethora-of-options"><i class="fa fa-check"></i><b>10.2</b> Plethora of Options</a></li>
<li class="chapter" data-level="10.3" data-path="final-revisions.html"><a href="final-revisions.html#interface-design"><i class="fa fa-check"></i><b>10.3</b> Interface Design</a></li>
</ul></li>
<li class="chapter" data-level="11" data-path="excercise-ploty.html"><a href="excercise-ploty.html"><i class="fa fa-check"></i><b>11</b> Excercise - Ploty</a>
<ul>
<li class="chapter" data-level="11.1" data-path="excercise-ploty.html"><a href="excercise-ploty.html#discover-plotly"><i class="fa fa-check"></i><b>11.1</b> Discover Plotly</a></li>
<li class="chapter" data-level="11.2" data-path="excercise-ploty.html"><a href="excercise-ploty.html#basics-of-plotly"><i class="fa fa-check"></i><b>11.2</b> Basics of Plotly</a></li>
<li class="chapter" data-level="11.3" data-path="excercise-ploty.html"><a href="excercise-ploty.html#plotly.js-to-r"><i class="fa fa-check"></i><b>11.3</b> Plotly.js to R</a></li>
<li class="chapter" data-level="11.4" data-path="excercise-ploty.html"><a href="excercise-ploty.html#r-to-plotly.js"><i class="fa fa-check"></i><b>11.4</b> R to Plotly.js</a></li>
<li class="chapter" data-level="11.5" data-path="excercise-ploty.html"><a href="excercise-ploty.html#size-resize-plotly.js"><i class="fa fa-check"></i><b>11.5</b> Size &amp; Resize Plotly.js</a></li>
<li class="chapter" data-level="11.6" data-path="excercise-ploty.html"><a href="excercise-ploty.html#performance-security-with-plotly.js"><i class="fa fa-check"></i><b>11.6</b> Performance &amp; Security with Plotly.js</a></li>
</ul></li>
<li class="part"><span><b>III Web Development with Shiny</b></span></li>
<li class="chapter" data-level="12" data-path="introduction-to-shiny.html"><a href="introduction-to-shiny.html"><i class="fa fa-check"></i><b>12</b> Introduction to Shiny</a>
<ul>
<li class="chapter" data-level="12.1" data-path="introduction-to-shiny.html"><a href="introduction-to-shiny.html#websocket-shiny"><i class="fa fa-check"></i><b>12.1</b> Websocket &amp; Shiny</a></li>
<li class="chapter" data-level="12.2" data-path="introduction-to-shiny.html"><a href="introduction-to-shiny.html#alerts-an-example"><i class="fa fa-check"></i><b>12.2</b> Alerts, An Example</a></li>
<li class="chapter" data-level="12.3" data-path="introduction-to-shiny.html"><a href="introduction-to-shiny.html#alerts-r-to-js"><i class="fa fa-check"></i><b>12.3</b> From R to JavaScript</a></li>
<li class="chapter" data-level="12.4" data-path="introduction-to-shiny.html"><a href="introduction-to-shiny.html#alerts-js-to-r"><i class="fa fa-check"></i><b>12.4</b> From JavaScript to R</a></li>
<li class="chapter" data-level="12.5" data-path="introduction-to-shiny.html"><a href="introduction-to-shiny.html#alerts-deserialise"><i class="fa fa-check"></i><b>12.5</b> Deserialise</a></li>
</ul></li>
<li class="chapter" data-level="13" data-path="a-complete-integration.html"><a href="a-complete-integration.html"><i class="fa fa-check"></i><b>13</b> A Complete Integration</a>
<ul>
<li class="chapter" data-level="13.1" data-path="a-complete-integration.html"><a href="a-complete-integration.html#serialisation"><i class="fa fa-check"></i><b>13.1</b> Serialisation</a></li>
<li class="chapter" data-level="13.2" data-path="a-complete-integration.html"><a href="a-complete-integration.html#events-callbacks"><i class="fa fa-check"></i><b>13.2</b> Events &amp; Callbacks</a></li>
<li class="chapter" data-level="13.3" data-path="a-complete-integration.html"><a href="a-complete-integration.html#as-a-package"><i class="fa fa-check"></i><b>13.3</b> As a Package</a>
<ul>
<li class="chapter" data-level="13.3.1" data-path="advanced-topics.html"><a href="advanced-topics.html#dependencies"><i class="fa fa-check"></i><b>13.3.1</b> Dependencies</a></li>
<li class="chapter" data-level="13.3.2" data-path="prerequisites.html"><a href="prerequisites.html#r-code"><i class="fa fa-check"></i><b>13.3.2</b> R Code</a></li>
<li class="chapter" data-level="13.3.3" data-path="advanced-topics.html"><a href="advanced-topics.html#javascript-code"><i class="fa fa-check"></i><b>13.3.3</b> JavaScript Code</a></li>
<li class="chapter" data-level="13.3.4" data-path="a-complete-integration.html"><a href="a-complete-integration.html#input-handler"><i class="fa fa-check"></i><b>13.3.4</b> Input Handler</a></li>
<li class="chapter" data-level="13.3.5" data-path="a-complete-integration.html"><a href="a-complete-integration.html#wrapping-up"><i class="fa fa-check"></i><b>13.3.5</b> Wrapping up</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="14" data-path="tips-tricks.html"><a href="tips-tricks.html"><i class="fa fa-check"></i><b>14</b> Tips &amp; Tricks</a>
<ul>
<li class="chapter" data-level="14.1" data-path="tips-tricks.html"><a href="tips-tricks.html#shiny-events"><i class="fa fa-check"></i><b>14.1</b> Shiny Events</a></li>
<li class="chapter" data-level="14.2" data-path="tips-tricks.html"><a href="tips-tricks.html#table-buttons"><i class="fa fa-check"></i><b>14.2</b> Table Buttons</a></li>
<li class="chapter" data-level="14.3" data-path="tips-tricks.html"><a href="tips-tricks.html#jquery---toggle"><i class="fa fa-check"></i><b>14.3</b> jQuery - Toggle</a></li>
</ul></li>
<li class="chapter" data-level="15" data-path="custom-outputs.html"><a href="custom-outputs.html"><i class="fa fa-check"></i><b>15</b> Custom Outputs</a>
<ul>
<li class="chapter" data-level="15.1" data-path="custom-outputs.html"><a href="custom-outputs.html#custom-outputs-inner-workings"><i class="fa fa-check"></i><b>15.1</b> Custom Outputs Inner-workings</a></li>
<li class="chapter" data-level="15.2" data-path="custom-outputs.html"><a href="custom-outputs.html#setup-custom-output"><i class="fa fa-check"></i><b>15.2</b> Setup Custom Output</a></li>
<li class="chapter" data-level="15.3" data-path="custom-outputs.html"><a href="custom-outputs.html#output-r-function"><i class="fa fa-check"></i><b>15.3</b> Output R Function</a></li>
<li class="chapter" data-level="15.4" data-path="custom-outputs.html"><a href="custom-outputs.html#generate-output-html"><i class="fa fa-check"></i><b>15.4</b> Generate Output HTML</a></li>
<li class="chapter" data-level="15.5" data-path="custom-outputs.html"><a href="custom-outputs.html#output-renderer"><i class="fa fa-check"></i><b>15.5</b> Output Renderer</a></li>
<li class="chapter" data-level="15.6" data-path="custom-outputs.html"><a href="custom-outputs.html#javascript-output-binding"><i class="fa fa-check"></i><b>15.6</b> JavaScript Output Binding</a>
<ul>
<li class="chapter" data-level="15.6.1" data-path="custom-outputs.html"><a href="custom-outputs.html#boxxy-title"><i class="fa fa-check"></i><b>15.6.1</b> Boxxy title</a></li>
<li class="chapter" data-level="15.6.2" data-path="custom-outputs.html"><a href="custom-outputs.html#boxxy-value"><i class="fa fa-check"></i><b>15.6.2</b> Boxxy value</a></li>
<li class="chapter" data-level="15.6.3" data-path="custom-outputs.html"><a href="custom-outputs.html#boxxy-background-color"><i class="fa fa-check"></i><b>15.6.3</b> Boxxy Background Color</a></li>
<li class="chapter" data-level="15.6.4" data-path="custom-outputs.html"><a href="custom-outputs.html#register-the-output-binding"><i class="fa fa-check"></i><b>15.6.4</b> Register the Output Binding</a></li>
</ul></li>
<li class="chapter" data-level="15.7" data-path="custom-outputs.html"><a href="custom-outputs.html#boxxy-usage"><i class="fa fa-check"></i><b>15.7</b> Boxxy Usage</a></li>
<li class="chapter" data-level="15.8" data-path="custom-outputs.html"><a href="custom-outputs.html#injecting-dependencies"><i class="fa fa-check"></i><b>15.8</b> Injecting Dependencies</a></li>
<li class="chapter" data-level="15.9" data-path="custom-outputs.html"><a href="custom-outputs.html#preprocessing-custom-outputs"><i class="fa fa-check"></i><b>15.9</b> Preprocessing Custom Outputs</a></li>
</ul></li>
<li class="chapter" data-level="16" data-path="custom-inputs.html"><a href="custom-inputs.html"><i class="fa fa-check"></i><b>16</b> Custom Inputs</a>
<ul>
<li class="chapter" data-level="16.1" data-path="custom-inputs.html"><a href="custom-inputs.html#setup-custom-input"><i class="fa fa-check"></i><b>16.1</b> Setup Custom Input</a></li>
<li class="chapter" data-level="16.2" data-path="custom-inputs.html"><a href="custom-inputs.html#switch-input-html-style"><i class="fa fa-check"></i><b>16.2</b> Switch Input HTML &amp; Style</a></li>
<li class="chapter" data-level="16.3" data-path="custom-inputs.html"><a href="custom-inputs.html#generate-input-html"><i class="fa fa-check"></i><b>16.3</b> Generate Input HTML</a></li>
<li class="chapter" data-level="16.4" data-path="custom-inputs.html"><a href="custom-inputs.html#javascript-input-binding"><i class="fa fa-check"></i><b>16.4</b> JavaScript Input Binding</a>
<ul>
<li class="chapter" data-level="16.4.1" data-path="custom-inputs.html"><a href="custom-inputs.html#find-inputs"><i class="fa fa-check"></i><b>16.4.1</b> Find Inputs</a></li>
<li class="chapter" data-level="16.4.2" data-path="custom-inputs.html"><a href="custom-inputs.html#get-input-id"><i class="fa fa-check"></i><b>16.4.2</b> Get Input Id</a></li>
<li class="chapter" data-level="16.4.3" data-path="custom-inputs.html"><a href="custom-inputs.html#get-input-value"><i class="fa fa-check"></i><b>16.4.3</b> Get Input Value</a></li>
<li class="chapter" data-level="16.4.4" data-path="custom-inputs.html"><a href="custom-inputs.html#set-input-value"><i class="fa fa-check"></i><b>16.4.4</b> Set Input Value</a></li>
<li class="chapter" data-level="16.4.5" data-path="custom-inputs.html"><a href="custom-inputs.html#receive-input-messages"><i class="fa fa-check"></i><b>16.4.5</b> Receive Input Messages</a></li>
<li class="chapter" data-level="16.4.6" data-path="custom-inputs.html"><a href="custom-inputs.html#subscribe-unsubscribe-inputs"><i class="fa fa-check"></i><b>16.4.6</b> Subscribe &amp; Unsubscribe Inputs</a></li>
<li class="chapter" data-level="16.4.7" data-path="custom-inputs.html"><a href="custom-inputs.html#input-rate-policy"><i class="fa fa-check"></i><b>16.4.7</b> Input Rate Policy</a></li>
<li class="chapter" data-level="16.4.8" data-path="custom-inputs.html"><a href="custom-inputs.html#registering-the-input"><i class="fa fa-check"></i><b>16.4.8</b> Registering the Input</a></li>
</ul></li>
<li class="chapter" data-level="16.5" data-path="custom-inputs.html"><a href="custom-inputs.html#update-input"><i class="fa fa-check"></i><b>16.5</b> Update Input</a></li>
<li class="chapter" data-level="16.6" data-path="custom-inputs.html"><a href="custom-inputs.html#exercise"><i class="fa fa-check"></i><b>16.6</b> Exercise</a></li>
</ul></li>
<li class="chapter" data-level="17" data-path="cookies.html"><a href="cookies.html"><i class="fa fa-check"></i><b>17</b> Cookies</a>
<ul>
<li class="chapter" data-level="17.1" data-path="cookies.html"><a href="cookies.html#discover-js-cookie"><i class="fa fa-check"></i><b>17.1</b> Discover js-cookie</a></li>
<li class="chapter" data-level="17.2" data-path="cookies.html"><a href="cookies.html#setup-cookies-project"><i class="fa fa-check"></i><b>17.2</b> Setup Cookies Project</a></li>
<li class="chapter" data-level="17.3" data-path="cookies.html"><a href="cookies.html#javascript-cookies"><i class="fa fa-check"></i><b>17.3</b> JavaScript Cookies</a></li>
<li class="chapter" data-level="17.4" data-path="cookies.html"><a href="cookies.html#r-code-for-cookies"><i class="fa fa-check"></i><b>17.4</b> R Code for Cookies</a></li>
</ul></li>
<li class="chapter" data-level="18" data-path="widgets-with-shiny.html"><a href="widgets-with-shiny.html"><i class="fa fa-check"></i><b>18</b> Widgets with Shiny</a>
<ul>
<li class="chapter" data-level="18.1" data-path="widgets-with-shiny.html"><a href="widgets-with-shiny.html#widgets-to-r"><i class="fa fa-check"></i><b>18.1</b> Widgets to R</a></li>
<li class="chapter" data-level="18.2" data-path="widgets-with-shiny.html"><a href="widgets-with-shiny.html#input-handlers-for-widgets"><i class="fa fa-check"></i><b>18.2</b> Input Handlers for Widgets</a></li>
<li class="chapter" data-level="18.3" data-path="widgets-with-shiny.html"><a href="widgets-with-shiny.html#r-to-widgets"><i class="fa fa-check"></i><b>18.3</b> R to Widgets</a>
<ul>
<li class="chapter" data-level="18.3.1" data-path="widgets-with-shiny.html"><a href="widgets-with-shiny.html#send-data-from-widgets"><i class="fa fa-check"></i><b>18.3.1</b> Send Data from Widgets</a></li>
<li class="chapter" data-level="18.3.2" data-path="widgets-with-shiny.html"><a href="widgets-with-shiny.html#retrieve-widget-instance"><i class="fa fa-check"></i><b>18.3.2</b> Retrieve Widget Instance</a></li>
<li class="chapter" data-level="18.3.3" data-path="widgets-with-shiny.html"><a href="widgets-with-shiny.html#handle-data"><i class="fa fa-check"></i><b>18.3.3</b> Handle Data</a></li>
</ul></li>
<li class="chapter" data-level="18.4" data-path="widgets-with-shiny.html"><a href="widgets-with-shiny.html#proxy-function"><i class="fa fa-check"></i><b>18.4</b> Proxy Function</a></li>
<li class="chapter" data-level="18.5" data-path="widgets-with-shiny.html"><a href="widgets-with-shiny.html#clear-data"><i class="fa fa-check"></i><b>18.5</b> Clear Data</a></li>
<li class="chapter" data-level="18.6" data-path="widgets-with-shiny.html"><a href="widgets-with-shiny.html#update-the-widget"><i class="fa fa-check"></i><b>18.6</b> Update the Widget</a></li>
</ul></li>
<li class="part"><span><b>IV Interactive Documents</b></span></li>
<li class="chapter" data-level="19" data-path="introduction-to-rmarkdown.html"><a href="introduction-to-rmarkdown.html"><i class="fa fa-check"></i><b>19</b> Introduction to Rmarkdown</a></li>
<li class="part"><span><b>V JavaScript for Computations</b></span></li>
<li class="chapter" data-level="20" data-path="the-v8-engine.html"><a href="the-v8-engine.html"><i class="fa fa-check"></i><b>20</b> The V8 Engine</a>
<ul>
<li class="chapter" data-level="20.1" data-path="the-v8-engine.html"><a href="the-v8-engine.html#installation"><i class="fa fa-check"></i><b>20.1</b> Installation</a></li>
<li class="chapter" data-level="20.2" data-path="the-v8-engine.html"><a href="the-v8-engine.html#basics"><i class="fa fa-check"></i><b>20.2</b> Basics</a></li>
<li class="chapter" data-level="20.3" data-path="the-v8-engine.html"><a href="the-v8-engine.html#external-libraries"><i class="fa fa-check"></i><b>20.3</b> External Libraries</a></li>
<li class="chapter" data-level="20.4" data-path="the-v8-engine.html"><a href="the-v8-engine.html#with-npm"><i class="fa fa-check"></i><b>20.4</b> With Npm</a></li>
<li class="chapter" data-level="20.5" data-path="the-v8-engine.html"><a href="the-v8-engine.html#use-in-packages"><i class="fa fa-check"></i><b>20.5</b> Use in Packages</a></li>
</ul></li>
<li class="chapter" data-level="21" data-path="exercise-machine-learning.html"><a href="exercise-machine-learning.html"><i class="fa fa-check"></i><b>21</b> Exercise - Machine Learning</a>
<ul>
<li class="chapter" data-level="21.1" data-path="exercise-machine-learning.html"><a href="exercise-machine-learning.html#dependency"><i class="fa fa-check"></i><b>21.1</b> Dependency</a></li>
<li class="chapter" data-level="21.2" data-path="exercise-machine-learning.html"><a href="exercise-machine-learning.html#simple-regression"><i class="fa fa-check"></i><b>21.2</b> Simple Regression</a></li>
</ul></li>
<li class="part"><span><b>VI Examples</b></span></li>
<li class="chapter" data-level="22" data-path="image-classifier.html"><a href="image-classifier.html"><i class="fa fa-check"></i><b>22</b> Image Classifier</a>
<ul>
<li class="chapter" data-level="22.1" data-path="image-classifier.html"><a href="image-classifier.html#discover"><i class="fa fa-check"></i><b>22.1</b> Discover</a></li>
<li class="chapter" data-level="22.2" data-path="image-classifier.html"><a href="image-classifier.html#setup"><i class="fa fa-check"></i><b>22.2</b> Setup</a></li>
<li class="chapter" data-level="22.3" data-path="prerequisites.html"><a href="prerequisites.html#javascript"><i class="fa fa-check"></i><b>22.3</b> JavaScript</a></li>
<li class="chapter" data-level="22.4" data-path="a-complete-integration.html"><a href="a-complete-integration.html#input-handler"><i class="fa fa-check"></i><b>22.4</b> Input Handler</a></li>
</ul></li>
<li class="chapter" data-level="23" data-path="progress-bar.html"><a href="progress-bar.html"><i class="fa fa-check"></i><b>23</b> Progress Bar</a>
<ul>
<li class="chapter" data-level="23.1" data-path="prerequisites.html"><a href="prerequisites.html#r-code"><i class="fa fa-check"></i><b>23.1</b> R code</a></li>
<li class="chapter" data-level="23.2" data-path="advanced-topics.html"><a href="advanced-topics.html#javascript-code"><i class="fa fa-check"></i><b>23.2</b> JavaScript code</a></li>
<li class="chapter" data-level="23.3" data-path="progress-bar.html"><a href="progress-bar.html#events"><i class="fa fa-check"></i><b>23.3</b> Events</a></li>
</ul></li>
<li class="part"><span><b>VII Closing Remarks</b></span></li>
<li class="chapter" data-level="24" data-path="conclusion.html"><a href="conclusion.html"><i class="fa fa-check"></i><b>24</b> Conclusion</a>
<ul>
<li class="chapter" data-level="24.1" data-path="advanced-topics.html"><a href="advanced-topics.html#performances"><i class="fa fa-check"></i><b>24.1</b> Performances</a></li>
<li class="chapter" data-level="24.2" data-path="conclusion.html"><a href="conclusion.html#road-ahead"><i class="fa fa-check"></i><b>24.2</b> Road ahead</a>
<ul>
<li class="chapter" data-level="24.2.1" data-path="conclusion.html"><a href="conclusion.html#computation"><i class="fa fa-check"></i><b>24.2.1</b> Computation</a></li>
<li class="chapter" data-level="24.2.2" data-path="overview.html"><a href="overview.html#shiny"><i class="fa fa-check"></i><b>24.2.2</b> Shiny</a></li>
<li class="chapter" data-level="24.2.3" data-path="overview.html"><a href="overview.html#htmlwidgets"><i class="fa fa-check"></i><b>24.2.3</b> htmlwidgets</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="" data-path="references.html"><a href="references.html"><i class="fa fa-check"></i>References</a></li>
</ul>

      </nav>
    </div>

    <div class="book-body">
      <div class="body-inner">
        <div class="book-header" role="navigation">
          <h1>
            <i class="fa fa-circle-o-notch fa-spin"></i><a href="./">JavaScript for R</a>
          </h1>
        </div>

        <div class="page-wrapper" tabindex="-1" role="main">
          <div class="page-inner">

            <section class="normal" id="section-">
<div id="custom-outputs" class="section level1" number="15">
<h1><span class="header-section-number">Chapter 15</span> Custom Outputs</h1>
<p>In this chapter we create a custom shiny output, in practical terms this creates custom <code>render*</code> and <code>*Output</code> functions to use in Shiny. This will be demonstrated by creating something akin to the <code>valueBox</code> available in the shinydashboard <span class="citation">(Chang and Borges Ribeiro <a href="#ref-R-shinydashboard" role="doc-biblioref">2018</a>)</span> package. While similar to what shinydashboard provides this box will 1) be fully customisable and 2) available in any shiny application 3) have additional functionalities.</p>
<p>The <code>valueBox</code> equivalent we shall build in this chapter is named “boxxy,” and allows creating simple but colourful value boxes with animated numbers (by counting up to it) using <a href="https://github.com/inorganik/countUp.js">countUp.js</a>.</p>
<div class="sourceCode" id="cb307"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb307-1"><a href="custom-outputs.html#cb307-1"></a><span class="kw">library</span>(shiny)</span>
<span id="cb307-2"><a href="custom-outputs.html#cb307-2"></a></span>
<span id="cb307-3"><a href="custom-outputs.html#cb307-3"></a>ui &lt;-<span class="st"> </span><span class="kw">fluidPage</span>(</span>
<span id="cb307-4"><a href="custom-outputs.html#cb307-4"></a>  <span class="kw">boxxyOutput</span>(<span class="st">&quot;countries&quot;</span>)</span>
<span id="cb307-5"><a href="custom-outputs.html#cb307-5"></a>)</span>
<span id="cb307-6"><a href="custom-outputs.html#cb307-6"></a></span>
<span id="cb307-7"><a href="custom-outputs.html#cb307-7"></a>server &lt;-<span class="st"> </span><span class="cf">function</span>(input, output){</span>
<span id="cb307-8"><a href="custom-outputs.html#cb307-8"></a>  output<span class="op">$</span>countries &lt;-<span class="st"> </span><span class="kw">renderBoxxy</span>({</span>
<span id="cb307-9"><a href="custom-outputs.html#cb307-9"></a>    <span class="kw">boxxy</span>(<span class="st">&quot;Countries&quot;</span>, <span class="dv">95</span>)</span>
<span id="cb307-10"><a href="custom-outputs.html#cb307-10"></a>  })</span>
<span id="cb307-11"><a href="custom-outputs.html#cb307-11"></a>}</span>
<span id="cb307-12"><a href="custom-outputs.html#cb307-12"></a></span>
<span id="cb307-13"><a href="custom-outputs.html#cb307-13"></a><span class="kw">shinyApp</span>(ui, server)</span></code></pre></div>
<div class="figure">
<img src="images/boxxy-example.png" alt="" />
<p class="caption">Custom output example</p>
</div>
<div id="custom-outputs-inner-workings" class="section level2" number="15.1">
<h2><span class="header-section-number">15.1</span> Custom Outputs Inner-workings</h2>
<p>At the core, this consists in creating three functions; <code>boxxy</code>, <code>renderBoxxy</code> and <code>boxxyOutput</code> (analogous to <code>plot</code>, <code>renderPlot</code>, <code>plotOutput</code>) which are linked by an “output binding” in JavaScript.</p>
<p>The first function, <code>boxxy</code> will accept arguments that help define what is in the box. This function is generally useful to preprocess any of the arguments that are meant to produce the custom output. The <code>boxxyOutput</code> function essentially creates the scaffold of the HTML output (e.g.: <code>&lt;div&gt;</code>) as well as the dependencies. The <code>render*</code> function is perhaps more peculiar it should accept an expression and return a function.</p>
<p>Previous work with shiny and JavaScript covered in this book had no dedicated “output” element that were placed in the shiny UI, therefore one had to use a function solely dedicated to importing the dependencies (e.g.: <code>usejBox</code>). However, since this is not the case here the dependencies can be attached together with the output.</p>
<p>Finally, the two R functions are “bound” JavaScript-side with an “output binding” that renders the data from the <code>render*</code> function with its <code>*output</code>.</p>
</div>
<div id="setup-custom-output" class="section level2" number="15.2">
<h2><span class="header-section-number">15.2</span> Setup Custom Output</h2>
<p>The custom output will be part of a shiny application, let us thus create the basic skeleton of an application and download the dependencies. Create a project in RStudio or an empty directory, then:</p>
<ol style="list-style-type: decimal">
<li>Create an <code>app.R</code> file that will hold the code for the application and <code>boxxy</code>, <code>boxxyOutput</code>, and <code>renderBoxxy</code> functions</li>
<li>Create an <code>assets</code> directory that will contain the CSS and JavaScript files.</li>
<li>Download the countUp.js dependency.</li>
<li>Create a <code>binding.js</code> JavaScript file for the JavaScript binding within the previously created <code>assets</code> directory.</li>
<li>Create a <code>styles.css</code> file in the <code>assets</code> directory.</li>
</ol>
<div class="sourceCode" id="cb308"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb308-1"><a href="custom-outputs.html#cb308-1"></a><span class="co"># application file</span></span>
<span id="cb308-2"><a href="custom-outputs.html#cb308-2"></a><span class="kw">file.create</span>(<span class="st">&quot;app.R&quot;</span>)</span>
<span id="cb308-3"><a href="custom-outputs.html#cb308-3"></a></span>
<span id="cb308-4"><a href="custom-outputs.html#cb308-4"></a><span class="co"># static file directory</span></span>
<span id="cb308-5"><a href="custom-outputs.html#cb308-5"></a><span class="kw">dir.create</span>(<span class="st">&quot;assets&quot;</span>)</span>
<span id="cb308-6"><a href="custom-outputs.html#cb308-6"></a></span>
<span id="cb308-7"><a href="custom-outputs.html#cb308-7"></a><span class="co"># countup dependency</span></span>
<span id="cb308-8"><a href="custom-outputs.html#cb308-8"></a>url &lt;-<span class="st"> </span><span class="kw">paste0</span>(</span>
<span id="cb308-9"><a href="custom-outputs.html#cb308-9"></a>  <span class="st">&quot;https://cdn.jsdelivr.net/npm/&quot;</span>,</span>
<span id="cb308-10"><a href="custom-outputs.html#cb308-10"></a>  <span class="st">&quot;countup@1.8.2/countUp.js&quot;</span></span>
<span id="cb308-11"><a href="custom-outputs.html#cb308-11"></a>)</span>
<span id="cb308-12"><a href="custom-outputs.html#cb308-12"></a></span>
<span id="cb308-13"><a href="custom-outputs.html#cb308-13"></a><span class="kw">download.file</span>(url, <span class="st">&quot;assets/countup.js&quot;</span>)</span>
<span id="cb308-14"><a href="custom-outputs.html#cb308-14"></a></span>
<span id="cb308-15"><a href="custom-outputs.html#cb308-15"></a><span class="co"># create binding file</span></span>
<span id="cb308-16"><a href="custom-outputs.html#cb308-16"></a><span class="kw">file.create</span>(<span class="st">&quot;assets/binding.js&quot;</span>)</span>
<span id="cb308-17"><a href="custom-outputs.html#cb308-17"></a></span>
<span id="cb308-18"><a href="custom-outputs.html#cb308-18"></a><span class="co"># CSS file</span></span>
<span id="cb308-19"><a href="custom-outputs.html#cb308-19"></a><span class="kw">file.create</span>(<span class="st">&quot;assets/styles.css&quot;</span>)</span></code></pre></div>
<p>This should produce the following directory structure.</p>
<pre><code>.
├── app.R
└── assets
    ├── binding.js
    ├── countup.js
    └── styles.css</code></pre>
</div>
<div id="output-r-function" class="section level2" number="15.3">
<h2><span class="header-section-number">15.3</span> Output R Function</h2>
<p>The <code>boxxy</code> function takes three arguments, a <code>title</code>, a <code>value</code> that will be animated and the background <code>color</code> to use for the box. The function, at this stage at least, does not preprocess the arguments and simply returns them as a named <code>list</code>.</p>
<div class="sourceCode" id="cb310"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb310-1"><a href="custom-outputs.html#cb310-1"></a><span class="co"># app.R</span></span>
<span id="cb310-2"><a href="custom-outputs.html#cb310-2"></a><span class="kw">library</span>(shiny)</span>
<span id="cb310-3"><a href="custom-outputs.html#cb310-3"></a></span>
<span id="cb310-4"><a href="custom-outputs.html#cb310-4"></a>boxxy &lt;-<span class="st"> </span><span class="cf">function</span>(title, value, <span class="dt">color =</span> <span class="st">&quot;#ef476f&quot;</span>){</span>
<span id="cb310-5"><a href="custom-outputs.html#cb310-5"></a>  <span class="kw">list</span>(<span class="dt">title =</span> title, <span class="dt">value =</span> value, <span class="dt">color =</span> color)</span>
<span id="cb310-6"><a href="custom-outputs.html#cb310-6"></a>}</span></code></pre></div>
</div>
<div id="generate-output-html" class="section level2" number="15.4">
<h2><span class="header-section-number">15.4</span> Generate Output HTML</h2>
<p>The <code>boxxyOutput</code> function, like all such functions (<code>plotOutput</code>, <code>uiOutput</code>, etc.) takes an <code>id</code>. This function should return an HTML tag which bears an <code>id</code>, or a <code>data-input-id</code> attribute (more on that later) and a <code>class</code>. The <code>id</code> is to be defined by the user of the function in Shiny just like any other such outputs. For instance, <code>plotOutput</code> creates a <code>&lt;div&gt;</code> the <code>id</code> of which is actually the <code>id</code> used in the <code>plotOutput</code> function.</p>
<div class="sourceCode" id="cb311"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb311-1"><a href="custom-outputs.html#cb311-1"></a><span class="co"># the id is used as id to the element</span></span>
<span id="cb311-2"><a href="custom-outputs.html#cb311-2"></a>shiny<span class="op">::</span><span class="kw">plotOutput</span>(<span class="dt">id =</span> <span class="st">&quot;myPlotId&quot;</span>)</span></code></pre></div>
<div class="sourceCode" id="cb312"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb312-1"><a href="custom-outputs.html#cb312-1"></a><span class="kw">&lt;div</span> </span>
<span id="cb312-2"><a href="custom-outputs.html#cb312-2"></a><span class="ot">  id=</span><span class="st">&quot;myPlotId&quot;</span> </span>
<span id="cb312-3"><a href="custom-outputs.html#cb312-3"></a><span class="ot">  class=</span><span class="st">&quot;shiny-plot-output&quot;</span> </span>
<span id="cb312-4"><a href="custom-outputs.html#cb312-4"></a><span class="ot">  style=</span><span class="st">&quot;width: 100% ; height: 400px&quot;</span><span class="kw">&gt;</span></span>
<span id="cb312-5"><a href="custom-outputs.html#cb312-5"></a><span class="kw">&lt;/div&gt;</span></span></code></pre></div>
<p>The <code>class</code> is used JavaScript-side to “find” the outputs in the DOM (document object model) and generate the output. The function <code>boxxyOutput</code> could thus be as shown below, the <code>id</code> is passed along to the <code>&lt;div&gt;</code> which is created with a <code>boxxy</code> class that will be used in the output binding to find that element and generate the output within that very <code>&lt;div&gt;</code> using data that will be passed from the server.</p>
<div class="sourceCode" id="cb313"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb313-1"><a href="custom-outputs.html#cb313-1"></a>boxxyOutput &lt;-<span class="st"> </span><span class="cf">function</span>(id){</span>
<span id="cb313-2"><a href="custom-outputs.html#cb313-2"></a>  <span class="co"># the HTML output</span></span>
<span id="cb313-3"><a href="custom-outputs.html#cb313-3"></a>  shiny<span class="op">::</span>tags<span class="op">$</span><span class="kw">div</span>(</span>
<span id="cb313-4"><a href="custom-outputs.html#cb313-4"></a>    <span class="dt">id =</span> id, <span class="dt">class =</span> <span class="st">&quot;boxxy&quot;</span></span>
<span id="cb313-5"><a href="custom-outputs.html#cb313-5"></a>  )</span>
<span id="cb313-6"><a href="custom-outputs.html#cb313-6"></a>}</span></code></pre></div>
<div class="rmdnote">
<p>
Make sure you use unique class names so they are not accidentally overridden by the user.
</p>
</div>
<p>As shown previously the box should include a title and an animated value. These could be generated entirely in JavaScript but it’s actually easier to create placeholders with htmltools tags, we generate dynamic ids for those so they can easily be referenced later on in JavaScript: <code>id-boxxy-value</code> for the value and <code>id-boxxy-title</code> for the title.</p>
<div class="sourceCode" id="cb314"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb314-1"><a href="custom-outputs.html#cb314-1"></a>boxxyOutput &lt;-<span class="st"> </span><span class="cf">function</span>(id){</span>
<span id="cb314-2"><a href="custom-outputs.html#cb314-2"></a>  <span class="co"># the HTML output</span></span>
<span id="cb314-3"><a href="custom-outputs.html#cb314-3"></a>  shiny<span class="op">::</span>tags<span class="op">$</span><span class="kw">div</span>(</span>
<span id="cb314-4"><a href="custom-outputs.html#cb314-4"></a>    <span class="dt">id =</span> id, <span class="dt">class =</span> <span class="st">&quot;boxxy&quot;</span>,</span>
<span id="cb314-5"><a href="custom-outputs.html#cb314-5"></a>    <span class="kw">h1</span>(</span>
<span id="cb314-6"><a href="custom-outputs.html#cb314-6"></a>      <span class="dt">id =</span> <span class="kw">sprintf</span>(<span class="st">&quot;%s-boxxy-value&quot;</span>, id), </span>
<span id="cb314-7"><a href="custom-outputs.html#cb314-7"></a>      <span class="dt">class =</span> <span class="st">&quot;boxxy-value&quot;</span></span>
<span id="cb314-8"><a href="custom-outputs.html#cb314-8"></a>    ),</span>
<span id="cb314-9"><a href="custom-outputs.html#cb314-9"></a>    <span class="kw">p</span>(</span>
<span id="cb314-10"><a href="custom-outputs.html#cb314-10"></a>      <span class="dt">id =</span> <span class="kw">sprintf</span>(<span class="st">&quot;%s-boxxy-title&quot;</span>, id), </span>
<span id="cb314-11"><a href="custom-outputs.html#cb314-11"></a>      <span class="dt">class =</span> <span class="st">&quot;boxxy-title&quot;</span></span>
<span id="cb314-12"><a href="custom-outputs.html#cb314-12"></a>    )</span>
<span id="cb314-13"><a href="custom-outputs.html#cb314-13"></a>  )</span>
<span id="cb314-14"><a href="custom-outputs.html#cb314-14"></a>}</span></code></pre></div>
<p>Finally, we also used classes in the output so every element it comprises can be styled with ease.</p>
<div class="sourceCode" id="cb315"><pre class="sourceCode css"><code class="sourceCode css"><span id="cb315-1"><a href="custom-outputs.html#cb315-1"></a><span class="fu">.boxxy</span>{</span>
<span id="cb315-2"><a href="custom-outputs.html#cb315-2"></a>  <span class="kw">text-align</span>: <span class="dv">center</span><span class="op">;</span></span>
<span id="cb315-3"><a href="custom-outputs.html#cb315-3"></a>  <span class="kw">border-left</span>: <span class="dv">6</span><span class="dt">px</span> <span class="dv">solid</span> <span class="cn">#073b4c</span><span class="op">;</span></span>
<span id="cb315-4"><a href="custom-outputs.html#cb315-4"></a>  <span class="kw">padding</span>: <span class="dv">1</span><span class="dt">em</span><span class="op">;</span></span>
<span id="cb315-5"><a href="custom-outputs.html#cb315-5"></a>}</span>
<span id="cb315-6"><a href="custom-outputs.html#cb315-6"></a></span>
<span id="cb315-7"><a href="custom-outputs.html#cb315-7"></a><span class="fu">.boxxy-title</span>{</span>
<span id="cb315-8"><a href="custom-outputs.html#cb315-8"></a>  <span class="kw">text-transform</span>: <span class="dv">uppercase</span><span class="op">;</span></span>
<span id="cb315-9"><a href="custom-outputs.html#cb315-9"></a>}</span>
<span id="cb315-10"><a href="custom-outputs.html#cb315-10"></a></span>
<span id="cb315-11"><a href="custom-outputs.html#cb315-11"></a><span class="fu">.boxxy-value</span>{</span>
<span id="cb315-12"><a href="custom-outputs.html#cb315-12"></a>  <span class="kw">font-size</span>: <span class="dv">3</span><span class="dt">em</span><span class="op">;</span></span>
<span id="cb315-13"><a href="custom-outputs.html#cb315-13"></a>}</span></code></pre></div>
<p>The dependencies should be added to the above, since this function must be placed in the UI for anything to work the dependencies can piggyback on the output element. This works using the htmltools package. The function <code>htmltools::htmlDependency</code> is used to create a dependency that is then attached with <code>htmltools::attachDependencies</code>. While the former creates an object that shiny can understand and translate into <code>&lt;script&gt;</code> or <code>&lt;style&gt;</code> tags, the former attaches them to the output object and ensures dependencies are not imported multiple times (e.g.: when <code>boxxyOutput</code> is used more than once).</p>
<p>Notice the use of <code>normalizePath</code> to retrieve the full path to the <code>assets</code> directory as this will not work with a relative path (e.g.: <code>./assets</code>). The dependencies consist of the three files previously created and necessary to generate the output: <code>countup.js</code> the dependency that was downloaded as well as <code>binding.js</code> and <code>styles.css</code>.</p>
<div class="sourceCode" id="cb316"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb316-1"><a href="custom-outputs.html#cb316-1"></a>boxxyOutput &lt;-<span class="st"> </span><span class="cf">function</span>(id){</span>
<span id="cb316-2"><a href="custom-outputs.html#cb316-2"></a>  el &lt;-<span class="st"> </span>tags<span class="op">$</span><span class="kw">div</span>(</span>
<span id="cb316-3"><a href="custom-outputs.html#cb316-3"></a>    <span class="dt">id =</span> id, <span class="dt">class =</span> <span class="st">&quot;boxxy&quot;</span>,</span>
<span id="cb316-4"><a href="custom-outputs.html#cb316-4"></a>    <span class="kw">h1</span>(</span>
<span id="cb316-5"><a href="custom-outputs.html#cb316-5"></a>      <span class="dt">id =</span> <span class="kw">sprintf</span>(<span class="st">&quot;%s-boxxy-counter&quot;</span>, id), </span>
<span id="cb316-6"><a href="custom-outputs.html#cb316-6"></a>      <span class="dt">class =</span> <span class="st">&quot;boxxy-value&quot;</span></span>
<span id="cb316-7"><a href="custom-outputs.html#cb316-7"></a>    ),</span>
<span id="cb316-8"><a href="custom-outputs.html#cb316-8"></a>    <span class="kw">p</span>(</span>
<span id="cb316-9"><a href="custom-outputs.html#cb316-9"></a>      <span class="dt">id =</span> <span class="kw">sprintf</span>(<span class="st">&quot;%s-boxxy-title&quot;</span>, id), </span>
<span id="cb316-10"><a href="custom-outputs.html#cb316-10"></a>      <span class="dt">class =</span> <span class="st">&quot;boxxy-title&quot;</span></span>
<span id="cb316-11"><a href="custom-outputs.html#cb316-11"></a>    )</span>
<span id="cb316-12"><a href="custom-outputs.html#cb316-12"></a>  )</span>
<span id="cb316-13"><a href="custom-outputs.html#cb316-13"></a></span>
<span id="cb316-14"><a href="custom-outputs.html#cb316-14"></a>  <span class="co"># get full path</span></span>
<span id="cb316-15"><a href="custom-outputs.html#cb316-15"></a>  path &lt;-<span class="st"> </span><span class="kw">normalizePath</span>(<span class="st">&quot;assets&quot;</span>)</span>
<span id="cb316-16"><a href="custom-outputs.html#cb316-16"></a></span>
<span id="cb316-17"><a href="custom-outputs.html#cb316-17"></a>  deps &lt;-<span class="st"> </span><span class="kw">list</span>(</span>
<span id="cb316-18"><a href="custom-outputs.html#cb316-18"></a>    htmltools<span class="op">::</span><span class="kw">htmlDependency</span>(</span>
<span id="cb316-19"><a href="custom-outputs.html#cb316-19"></a>      <span class="dt">name =</span> <span class="st">&quot;boxxy&quot;</span>,</span>
<span id="cb316-20"><a href="custom-outputs.html#cb316-20"></a>      <span class="dt">version =</span> <span class="st">&quot;1.0.0&quot;</span>,</span>
<span id="cb316-21"><a href="custom-outputs.html#cb316-21"></a>      <span class="dt">src =</span> <span class="kw">c</span>(<span class="dt">file =</span> path),</span>
<span id="cb316-22"><a href="custom-outputs.html#cb316-22"></a>      <span class="dt">script =</span> <span class="kw">c</span>(<span class="st">&quot;countup.js&quot;</span>, <span class="st">&quot;binding.js&quot;</span>),</span>
<span id="cb316-23"><a href="custom-outputs.html#cb316-23"></a>      <span class="dt">stylesheet =</span> <span class="st">&quot;styles.css&quot;</span></span>
<span id="cb316-24"><a href="custom-outputs.html#cb316-24"></a>    )</span>
<span id="cb316-25"><a href="custom-outputs.html#cb316-25"></a>  )</span>
<span id="cb316-26"><a href="custom-outputs.html#cb316-26"></a></span>
<span id="cb316-27"><a href="custom-outputs.html#cb316-27"></a>  htmltools<span class="op">::</span><span class="kw">attachDependencies</span>(el, deps)</span>
<span id="cb316-28"><a href="custom-outputs.html#cb316-28"></a>}</span></code></pre></div>
<p>Running the function reveals the HTML it generates at the exception of the dependencies which htmltools does not print to the console.</p>
<div class="sourceCode" id="cb317"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb317-1"><a href="custom-outputs.html#cb317-1"></a><span class="kw">boxxyOutput</span>(<span class="st">&quot;myID&quot;</span>)</span></code></pre></div>
<div class="sourceCode" id="cb318"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb318-1"><a href="custom-outputs.html#cb318-1"></a><span class="kw">&lt;div</span><span class="ot"> id=</span><span class="st">&quot;myID&quot;</span><span class="ot"> class=</span><span class="st">&quot;boxxy&quot;</span><span class="kw">&gt;</span></span>
<span id="cb318-2"><a href="custom-outputs.html#cb318-2"></a>  <span class="kw">&lt;h1</span><span class="ot"> id=</span><span class="st">&quot;myID-boxxy-counter&quot;</span><span class="ot"> class=</span><span class="st">&quot;boxxy-value&quot;</span><span class="kw">&gt;&lt;/h1&gt;</span></span>
<span id="cb318-3"><a href="custom-outputs.html#cb318-3"></a>  <span class="kw">&lt;p</span><span class="ot"> id=</span><span class="st">&quot;myID-boxxy-title&quot;</span><span class="ot"> class=</span><span class="st">&quot;boxxy-title&quot;</span><span class="kw">&gt;&lt;/p&gt;</span></span>
<span id="cb318-4"><a href="custom-outputs.html#cb318-4"></a><span class="kw">&lt;/div&gt;</span></span></code></pre></div>
</div>
<div id="output-renderer" class="section level2" number="15.5">
<h2><span class="header-section-number">15.5</span> Output Renderer</h2>
<p>The function <code>renderBoxxy</code> should accept an expression, like other such <code>render*</code> function. For instance in the example below the <code>renderPlot</code> function does accept an expression which uses, amongst other functions, <code>plot</code>.</p>
<div class="sourceCode" id="cb319"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb319-1"><a href="custom-outputs.html#cb319-1"></a>output<span class="op">$</span>myPlot &lt;-<span class="st"> </span><span class="kw">renderPlot</span>({</span>
<span id="cb319-2"><a href="custom-outputs.html#cb319-2"></a>  <span class="co"># this is an expression</span></span>
<span id="cb319-3"><a href="custom-outputs.html#cb319-3"></a>  cars <span class="op">%&gt;%</span><span class="st"> </span></span>
<span id="cb319-4"><a href="custom-outputs.html#cb319-4"></a><span class="st">    </span><span class="kw">head</span>() <span class="op">%&gt;%</span><span class="st"> </span></span>
<span id="cb319-5"><a href="custom-outputs.html#cb319-5"></a><span class="st">    </span><span class="kw">plot</span>()</span>
<span id="cb319-6"><a href="custom-outputs.html#cb319-6"></a>})</span></code></pre></div>
<p>The function <code>renderBoxxy</code> takes an expression and other arguments that are passed to <code>shiny::exprToFunction</code> this does pretty much what it says on the tin: it returns a function from an expression (unless that expression is a function, in which case it returns the expression). This function must be further wrapped in another as render functions must return functions.</p>
<div class="sourceCode" id="cb320"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb320-1"><a href="custom-outputs.html#cb320-1"></a>renderBoxxy &lt;-<span class="st"> </span><span class="cf">function</span>(expr, <span class="dt">env =</span> <span class="kw">parent.frame</span>(), </span>
<span id="cb320-2"><a href="custom-outputs.html#cb320-2"></a>  <span class="dt">quoted =</span> <span class="ot">FALSE</span>) {</span>
<span id="cb320-3"><a href="custom-outputs.html#cb320-3"></a>  <span class="co"># Convert the expression + environment into a function</span></span>
<span id="cb320-4"><a href="custom-outputs.html#cb320-4"></a>  func &lt;-<span class="st"> </span>shiny<span class="op">::</span><span class="kw">exprToFunction</span>(expr, env, quoted)</span>
<span id="cb320-5"><a href="custom-outputs.html#cb320-5"></a></span>
<span id="cb320-6"><a href="custom-outputs.html#cb320-6"></a>  <span class="cf">function</span>(){</span>
<span id="cb320-7"><a href="custom-outputs.html#cb320-7"></a>    <span class="kw">func</span>()</span>
<span id="cb320-8"><a href="custom-outputs.html#cb320-8"></a>  }</span>
<span id="cb320-9"><a href="custom-outputs.html#cb320-9"></a>}</span></code></pre></div>
</div>
<div id="javascript-output-binding" class="section level2" number="15.6">
<h2><span class="header-section-number">15.6</span> JavaScript Output Binding</h2>
<p>Here we create an “output binding,” it tells Shiny how to find the component and how to interact with it. An output binding is initialised from <code>Shiny.OutputBinding</code>. Below we initialise a new binding.</p>
<div class="sourceCode" id="cb321"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb321-1"><a href="custom-outputs.html#cb321-1"></a><span class="co">// custom.js</span></span>
<span id="cb321-2"><a href="custom-outputs.html#cb321-2"></a><span class="kw">var</span> boxxyBinding <span class="op">=</span> <span class="kw">new</span> Shiny<span class="op">.</span><span class="fu">OutputBinding</span>()<span class="op">;</span></span></code></pre></div>
<p>Then, this must be “extended” by specifying a number of methods, a very necessary one being <code>find</code>. It is used to look for the output HTML element in the document (<code>scope</code>), and return them as an array (<code>HTMLcollection</code>). Other methods all take an <code>el</code> argument; that value will always be an element that was returned from <code>find</code>. A very straightforward way to accomplish this is to use jQuery’s find method to identify elements with the <code>boxxy</code> class used in <code>boxxyOutput</code>. You are by no means forced to use a CSS class to identify the elements but there is no reason not to.</p>
<div class="sourceCode" id="cb322"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb322-1"><a href="custom-outputs.html#cb322-1"></a><span class="co">// custom.js</span></span>
<span id="cb322-2"><a href="custom-outputs.html#cb322-2"></a><span class="kw">var</span> boxxyBinding <span class="op">=</span> <span class="kw">new</span> Shiny<span class="op">.</span><span class="fu">OutputBinding</span>()<span class="op">;</span></span>
<span id="cb322-3"><a href="custom-outputs.html#cb322-3"></a></span>
<span id="cb322-4"><a href="custom-outputs.html#cb322-4"></a>$<span class="op">.</span><span class="fu">extend</span>(boxxyBinding<span class="op">,</span> {</span>
<span id="cb322-5"><a href="custom-outputs.html#cb322-5"></a>  <span class="dt">find</span><span class="op">:</span> <span class="kw">function</span>(scope) {</span>
<span id="cb322-6"><a href="custom-outputs.html#cb322-6"></a>    <span class="cf">return</span> $(scope)<span class="op">.</span><span class="fu">find</span>(<span class="st">&quot;.boxxy&quot;</span>)<span class="op">;</span></span>
<span id="cb322-7"><a href="custom-outputs.html#cb322-7"></a>  }</span>
<span id="cb322-8"><a href="custom-outputs.html#cb322-8"></a>})<span class="op">;</span></span></code></pre></div>
<p>One might then want to use the <code>getId</code> method which returns the <code>id</code> of the element, by default, as can be seen in the <a href="https://github.com/rstudio/shiny/blob/master/srcjs/output_binding.js">source code</a> (below), the binding returns the id as the <code>data-input-id</code> attribute and if that is falsy it returns the element’s <code>id</code>.</p>
<div class="sourceCode" id="cb323"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb323-1"><a href="custom-outputs.html#cb323-1"></a><span class="co">// getId default</span></span>
<span id="cb323-2"><a href="custom-outputs.html#cb323-2"></a><span class="kw">this</span><span class="op">.</span><span class="at">getId</span> <span class="op">=</span> <span class="kw">function</span>(el) {</span>
<span id="cb323-3"><a href="custom-outputs.html#cb323-3"></a>  <span class="cf">return</span> el[<span class="st">&#39;data-input-id&#39;</span>] <span class="op">||</span> el<span class="op">.</span><span class="at">id</span><span class="op">;</span></span>
<span id="cb323-4"><a href="custom-outputs.html#cb323-4"></a>}</span></code></pre></div>
<p>Since boxxy uses the element id the default will work and this can be skipped entirely.</p>
<p>Next, one needs to implement the <code>renderValue</code> function which is the very function that generates the output based on data used in <code>boxxy</code> and sent to the front-end with <code>renderBoxxy</code>. The <code>renderValue</code> method accepts two arguments, first <code>el</code> the element where the output should be generated, this is effectively the output of <code>boxxyOutput</code> which the binding found using <code>find</code>, the second argument is <code>data</code> which is the data passed to <code>boxxy</code> and serialised via <code>renderBoxxy</code>.</p>
<div class="rmdnote">
<p>
The <code>renderValue</code> is in effect very similar if not identical to the JavaScript function of the same name involved in creating htmlwidgets.
</p>
</div>
<div id="boxxy-title" class="section level3" number="15.6.1">
<h3><span class="header-section-number">15.6.1</span> Boxxy title</h3>
<p>Let’s now tackle the first of the three core aspect of the boxxy output: the title. The <code>title</code> should be placed in the previously created placeholder which bears the <code>id-boxxy-title</code>; exactly as was done with htmlwidgets previously we insert title (<code>data.title</code>) in the element with <code>innerText</code>. The dynamically generated id for the title is built in the same way it is in R, by concatenating the <code>id</code> with <code>-boxxy-title</code></p>
<ul>
<li>In R <code>sprintf("%s-boxxy-title", id)</code></li>
<li>In JavaScript <code>el.id + '-boxxy-title'</code></li>
</ul>
<div class="sourceCode" id="cb324"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb324-1"><a href="custom-outputs.html#cb324-1"></a><span class="kw">var</span> boxxyBinding <span class="op">=</span> <span class="kw">new</span> Shiny<span class="op">.</span><span class="fu">OutputBinding</span>()<span class="op">;</span></span>
<span id="cb324-2"><a href="custom-outputs.html#cb324-2"></a></span>
<span id="cb324-3"><a href="custom-outputs.html#cb324-3"></a>$<span class="op">.</span><span class="fu">extend</span>(boxxyBinding<span class="op">,</span> {</span>
<span id="cb324-4"><a href="custom-outputs.html#cb324-4"></a>  <span class="dt">find</span><span class="op">:</span> <span class="kw">function</span>(scope) {</span>
<span id="cb324-5"><a href="custom-outputs.html#cb324-5"></a>    <span class="cf">return</span> $(scope)<span class="op">.</span><span class="fu">find</span>(<span class="st">&quot;.boxxy&quot;</span>)<span class="op">;</span></span>
<span id="cb324-6"><a href="custom-outputs.html#cb324-6"></a>  }<span class="op">,</span></span>
<span id="cb324-7"><a href="custom-outputs.html#cb324-7"></a>  <span class="dt">renderValue</span><span class="op">:</span> <span class="kw">function</span>(el<span class="op">,</span> data) {</span>
<span id="cb324-8"><a href="custom-outputs.html#cb324-8"></a></span>
<span id="cb324-9"><a href="custom-outputs.html#cb324-9"></a>    <span class="co">// insert the title</span></span>
<span id="cb324-10"><a href="custom-outputs.html#cb324-10"></a>    <span class="kw">let</span> title_id <span class="op">=</span> el<span class="op">.</span><span class="at">id</span> <span class="op">+</span> <span class="st">&#39;-boxxy-title&#39;</span><span class="op">;</span></span>
<span id="cb324-11"><a href="custom-outputs.html#cb324-11"></a>    <span class="bu">document</span><span class="op">.</span><span class="fu">getElementById</span>(title_id)<span class="op">.</span><span class="at">innerText</span> <span class="op">=</span> data<span class="op">.</span><span class="at">title</span></span>
<span id="cb324-12"><a href="custom-outputs.html#cb324-12"></a>  }</span>
<span id="cb324-13"><a href="custom-outputs.html#cb324-13"></a>})<span class="op">;</span></span></code></pre></div>
</div>
<div id="boxxy-value" class="section level3" number="15.6.2">
<h3><span class="header-section-number">15.6.2</span> Boxxy value</h3>
<p>Though the custom output could be limited to a static value generated in a fashion similar to how the title is placed, we opted for a more fancy animated value using countUp.js.</p>
<p>Initialise a new counter, specifying the id of the element where it should be created, then as second argument the starting value from which the counter should start and finally the value to count up to. Note that there is a fourth argument to pass a JSON of options which we do not use here.</p>
<div class="sourceCode" id="cb325"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb325-1"><a href="custom-outputs.html#cb325-1"></a><span class="co">// place counter in elementId</span></span>
<span id="cb325-2"><a href="custom-outputs.html#cb325-2"></a><span class="co">// start at 0 and count up to 123</span></span>
<span id="cb325-3"><a href="custom-outputs.html#cb325-3"></a><span class="kw">const</span> counter <span class="op">=</span> <span class="kw">new</span> CountUp(<span class="st">&#39;elementId&#39;</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">123</span>)<span class="op">;</span></span>
<span id="cb325-4"><a href="custom-outputs.html#cb325-4"></a>counter<span class="op">.</span><span class="fu">start</span>()<span class="op">;</span></span></code></pre></div>
<p>The counter has to be generated in the <code>&lt;h1&gt;</code> placeholder bearing the <code>id-boxxy-value</code>, while the value to count up to is stored in <code>data.value</code> meaning the counter can be initialised with <code>new CountUp(el.id + '-boxxy-value', 0, data.value);</code>.</p>
<div class="sourceCode" id="cb326"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb326-1"><a href="custom-outputs.html#cb326-1"></a><span class="kw">var</span> boxxyBinding <span class="op">=</span> <span class="kw">new</span> Shiny<span class="op">.</span><span class="fu">OutputBinding</span>()<span class="op">;</span></span>
<span id="cb326-2"><a href="custom-outputs.html#cb326-2"></a></span>
<span id="cb326-3"><a href="custom-outputs.html#cb326-3"></a>$<span class="op">.</span><span class="fu">extend</span>(boxxyBinding<span class="op">,</span> {</span>
<span id="cb326-4"><a href="custom-outputs.html#cb326-4"></a>  <span class="dt">find</span><span class="op">:</span> <span class="kw">function</span>(scope) {</span>
<span id="cb326-5"><a href="custom-outputs.html#cb326-5"></a>    <span class="cf">return</span> $(scope)<span class="op">.</span><span class="fu">find</span>(<span class="st">&quot;.boxxy&quot;</span>)<span class="op">;</span></span>
<span id="cb326-6"><a href="custom-outputs.html#cb326-6"></a>  }<span class="op">,</span></span>
<span id="cb326-7"><a href="custom-outputs.html#cb326-7"></a>  <span class="dt">renderValue</span><span class="op">:</span> <span class="kw">function</span>(el<span class="op">,</span> data) {</span>
<span id="cb326-8"><a href="custom-outputs.html#cb326-8"></a></span>
<span id="cb326-9"><a href="custom-outputs.html#cb326-9"></a>    <span class="co">// insert the title</span></span>
<span id="cb326-10"><a href="custom-outputs.html#cb326-10"></a>    <span class="kw">let</span> title_id <span class="op">=</span> el<span class="op">.</span><span class="at">id</span> <span class="op">+</span> <span class="st">&#39;-boxxy-title&#39;</span><span class="op">;</span></span>
<span id="cb326-11"><a href="custom-outputs.html#cb326-11"></a>    <span class="bu">document</span><span class="op">.</span><span class="fu">getElementById</span>(title_id)<span class="op">.</span><span class="at">innerText</span> <span class="op">=</span> data<span class="op">.</span><span class="at">title</span></span>
<span id="cb326-12"><a href="custom-outputs.html#cb326-12"></a></span>
<span id="cb326-13"><a href="custom-outputs.html#cb326-13"></a>    <span class="co">// counter start at 0</span></span>
<span id="cb326-14"><a href="custom-outputs.html#cb326-14"></a>    <span class="kw">let</span> counter_id <span class="op">=</span> el<span class="op">.</span><span class="at">id</span> <span class="op">+</span> <span class="st">&#39;-boxxy-value&#39;</span><span class="op">;</span></span>
<span id="cb326-15"><a href="custom-outputs.html#cb326-15"></a>    <span class="kw">var</span> counter <span class="op">=</span> <span class="kw">new</span> CountUp(counter_id<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> data<span class="op">.</span><span class="at">value</span>)<span class="op">;</span></span>
<span id="cb326-16"><a href="custom-outputs.html#cb326-16"></a>    counter<span class="op">.</span><span class="fu">start</span>()<span class="op">;</span></span>
<span id="cb326-17"><a href="custom-outputs.html#cb326-17"></a>  }</span>
<span id="cb326-18"><a href="custom-outputs.html#cb326-18"></a>})<span class="op">;</span></span></code></pre></div>
</div>
<div id="boxxy-background-color" class="section level3" number="15.6.3">
<h3><span class="header-section-number">15.6.3</span> Boxxy Background Color</h3>
<p>Then we can set the background color that was passed to <code>boxxy</code> (<code>data.color</code>).</p>
<div class="sourceCode" id="cb327"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb327-1"><a href="custom-outputs.html#cb327-1"></a><span class="kw">var</span> boxxyBinding <span class="op">=</span> <span class="kw">new</span> Shiny<span class="op">.</span><span class="fu">OutputBinding</span>()<span class="op">;</span></span>
<span id="cb327-2"><a href="custom-outputs.html#cb327-2"></a></span>
<span id="cb327-3"><a href="custom-outputs.html#cb327-3"></a>$<span class="op">.</span><span class="fu">extend</span>(boxxyBinding<span class="op">,</span> {</span>
<span id="cb327-4"><a href="custom-outputs.html#cb327-4"></a>  <span class="dt">find</span><span class="op">:</span> <span class="kw">function</span>(scope) {</span>
<span id="cb327-5"><a href="custom-outputs.html#cb327-5"></a>    <span class="cf">return</span> $(scope)<span class="op">.</span><span class="fu">find</span>(<span class="st">&quot;.boxxy&quot;</span>)<span class="op">;</span></span>
<span id="cb327-6"><a href="custom-outputs.html#cb327-6"></a>  }<span class="op">,</span></span>
<span id="cb327-7"><a href="custom-outputs.html#cb327-7"></a>  <span class="dt">renderValue</span><span class="op">:</span> <span class="kw">function</span>(el<span class="op">,</span> data) {</span>
<span id="cb327-8"><a href="custom-outputs.html#cb327-8"></a></span>
<span id="cb327-9"><a href="custom-outputs.html#cb327-9"></a>    <span class="co">// insert the title</span></span>
<span id="cb327-10"><a href="custom-outputs.html#cb327-10"></a>    <span class="kw">let</span> title_id <span class="op">=</span> el<span class="op">.</span><span class="at">id</span> <span class="op">+</span> <span class="st">&#39;-boxxy-title&#39;</span><span class="op">;</span></span>
<span id="cb327-11"><a href="custom-outputs.html#cb327-11"></a>    <span class="bu">document</span><span class="op">.</span><span class="fu">getElementById</span>(title_id)<span class="op">.</span><span class="at">innerText</span> <span class="op">=</span> data<span class="op">.</span><span class="at">title</span></span>
<span id="cb327-12"><a href="custom-outputs.html#cb327-12"></a></span>
<span id="cb327-13"><a href="custom-outputs.html#cb327-13"></a>    <span class="co">// counter start at 0</span></span>
<span id="cb327-14"><a href="custom-outputs.html#cb327-14"></a>    <span class="kw">let</span> counter_id <span class="op">=</span> el<span class="op">.</span><span class="at">id</span> <span class="op">+</span> <span class="st">&#39;-boxxy-value&#39;</span><span class="op">;</span></span>
<span id="cb327-15"><a href="custom-outputs.html#cb327-15"></a>    <span class="kw">var</span> counter <span class="op">=</span> <span class="kw">new</span> CountUp(counter_id<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> data<span class="op">.</span><span class="at">value</span>)<span class="op">;</span></span>
<span id="cb327-16"><a href="custom-outputs.html#cb327-16"></a>    counter<span class="op">.</span><span class="fu">start</span>()<span class="op">;</span></span>
<span id="cb327-17"><a href="custom-outputs.html#cb327-17"></a></span>
<span id="cb327-18"><a href="custom-outputs.html#cb327-18"></a>    <span class="co">// background color </span></span>
<span id="cb327-19"><a href="custom-outputs.html#cb327-19"></a>    el<span class="op">.</span><span class="at">style</span><span class="op">.</span><span class="at">backgroundColor</span> <span class="op">=</span> data<span class="op">.</span><span class="at">color</span><span class="op">;</span></span>
<span id="cb327-20"><a href="custom-outputs.html#cb327-20"></a>  }</span>
<span id="cb327-21"><a href="custom-outputs.html#cb327-21"></a>})<span class="op">;</span></span></code></pre></div>
</div>
<div id="register-the-output-binding" class="section level3" number="15.6.4">
<h3><span class="header-section-number">15.6.4</span> Register the Output Binding</h3>
<p>Finally, the output binding must be registered with shiny. Note that it uses a unique string identifier, the <a href="https://shiny.rstudio.com/articles/building-outputs.html">documentation</a> states:</p>
<blockquote>
<p>At the moment it is unused but future features may depend on it.</p>
</blockquote>
<div class="sourceCode" id="cb328"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb328-1"><a href="custom-outputs.html#cb328-1"></a><span class="kw">var</span> boxxyBinding <span class="op">=</span> <span class="kw">new</span> Shiny<span class="op">.</span><span class="fu">OutputBinding</span>()<span class="op">;</span></span>
<span id="cb328-2"><a href="custom-outputs.html#cb328-2"></a></span>
<span id="cb328-3"><a href="custom-outputs.html#cb328-3"></a>$<span class="op">.</span><span class="fu">extend</span>(boxxyBinding<span class="op">,</span> {</span>
<span id="cb328-4"><a href="custom-outputs.html#cb328-4"></a>  <span class="dt">find</span><span class="op">:</span> <span class="kw">function</span>(scope) {</span>
<span id="cb328-5"><a href="custom-outputs.html#cb328-5"></a>    <span class="cf">return</span> $(scope)<span class="op">.</span><span class="fu">find</span>(<span class="st">&quot;.boxxy&quot;</span>)<span class="op">;</span></span>
<span id="cb328-6"><a href="custom-outputs.html#cb328-6"></a>  }<span class="op">,</span></span>
<span id="cb328-7"><a href="custom-outputs.html#cb328-7"></a>  <span class="dt">renderValue</span><span class="op">:</span> <span class="kw">function</span>(el<span class="op">,</span> data) {</span>
<span id="cb328-8"><a href="custom-outputs.html#cb328-8"></a></span>
<span id="cb328-9"><a href="custom-outputs.html#cb328-9"></a>    <span class="co">// insert the title</span></span>
<span id="cb328-10"><a href="custom-outputs.html#cb328-10"></a>    <span class="kw">let</span> title_id <span class="op">=</span> el<span class="op">.</span><span class="at">id</span> <span class="op">+</span> <span class="st">&#39;-boxxy-title&#39;</span><span class="op">;</span></span>
<span id="cb328-11"><a href="custom-outputs.html#cb328-11"></a>    <span class="bu">document</span><span class="op">.</span><span class="fu">getElementById</span>(title_id)<span class="op">.</span><span class="at">innerText</span> <span class="op">=</span> data<span class="op">.</span><span class="at">title</span></span>
<span id="cb328-12"><a href="custom-outputs.html#cb328-12"></a></span>
<span id="cb328-13"><a href="custom-outputs.html#cb328-13"></a>    <span class="co">// counter start at 0</span></span>
<span id="cb328-14"><a href="custom-outputs.html#cb328-14"></a>    <span class="kw">let</span> counter_id <span class="op">=</span> el<span class="op">.</span><span class="at">id</span> <span class="op">+</span> <span class="st">&#39;-boxxy-value&#39;</span><span class="op">;</span></span>
<span id="cb328-15"><a href="custom-outputs.html#cb328-15"></a>    <span class="kw">var</span> counter <span class="op">=</span> <span class="kw">new</span> CountUp(counter_id<span class="op">,</span> <span class="dv">0</span><span class="op">,</span> data<span class="op">.</span><span class="at">value</span>)<span class="op">;</span></span>
<span id="cb328-16"><a href="custom-outputs.html#cb328-16"></a>    counter<span class="op">.</span><span class="fu">start</span>()<span class="op">;</span></span>
<span id="cb328-17"><a href="custom-outputs.html#cb328-17"></a></span>
<span id="cb328-18"><a href="custom-outputs.html#cb328-18"></a>    <span class="co">// background color </span></span>
<span id="cb328-19"><a href="custom-outputs.html#cb328-19"></a>    el<span class="op">.</span><span class="at">style</span><span class="op">.</span><span class="at">backgroundColor</span> <span class="op">=</span> data<span class="op">.</span><span class="at">color</span><span class="op">;</span></span>
<span id="cb328-20"><a href="custom-outputs.html#cb328-20"></a>  }</span>
<span id="cb328-21"><a href="custom-outputs.html#cb328-21"></a>})<span class="op">;</span></span>
<span id="cb328-22"><a href="custom-outputs.html#cb328-22"></a></span>
<span id="cb328-23"><a href="custom-outputs.html#cb328-23"></a><span class="co">// register</span></span>
<span id="cb328-24"><a href="custom-outputs.html#cb328-24"></a>Shiny<span class="op">.</span><span class="at">outputBindings</span><span class="op">.</span><span class="fu">register</span>(boxxyBinding<span class="op">,</span> <span class="st">&quot;john.boxxy&quot;</span>)<span class="op">;</span></span></code></pre></div>
<p>Ensure that string uniquely identifies the binding to avoid future clash with other such bindings.</p>
</div>
</div>
<div id="boxxy-usage" class="section level2" number="15.7">
<h2><span class="header-section-number">15.7</span> Boxxy Usage</h2>
<p>With all of this in place one can use boxxy in a shiny application.</p>
<div class="sourceCode" id="cb329"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb329-1"><a href="custom-outputs.html#cb329-1"></a><span class="kw">library</span>(shiny)</span>
<span id="cb329-2"><a href="custom-outputs.html#cb329-2"></a></span>
<span id="cb329-3"><a href="custom-outputs.html#cb329-3"></a>boxxy &lt;-<span class="st"> </span><span class="cf">function</span>(title, value, <span class="dt">color =</span> <span class="st">&quot;black&quot;</span>){</span>
<span id="cb329-4"><a href="custom-outputs.html#cb329-4"></a>  <span class="kw">list</span>(<span class="dt">title =</span> title, <span class="dt">value =</span> value, <span class="dt">color =</span> color)</span>
<span id="cb329-5"><a href="custom-outputs.html#cb329-5"></a>}</span>
<span id="cb329-6"><a href="custom-outputs.html#cb329-6"></a></span>
<span id="cb329-7"><a href="custom-outputs.html#cb329-7"></a>boxxyOutput &lt;-<span class="st"> </span><span class="cf">function</span>(id){</span>
<span id="cb329-8"><a href="custom-outputs.html#cb329-8"></a>  el &lt;-<span class="st"> </span>shiny<span class="op">::</span>tags<span class="op">$</span><span class="kw">div</span>(</span>
<span id="cb329-9"><a href="custom-outputs.html#cb329-9"></a>    <span class="dt">id =</span> id, <span class="dt">class =</span> <span class="st">&quot;boxxy&quot;</span>,</span>
<span id="cb329-10"><a href="custom-outputs.html#cb329-10"></a>    <span class="kw">h1</span>(<span class="dt">id =</span> <span class="kw">sprintf</span>(<span class="st">&quot;%s-boxxy-value&quot;</span>, id), <span class="dt">class =</span> <span class="st">&quot;boxxy-value&quot;</span>),</span>
<span id="cb329-11"><a href="custom-outputs.html#cb329-11"></a>    <span class="kw">p</span>(<span class="dt">id =</span> <span class="kw">sprintf</span>(<span class="st">&quot;%s-boxxy-title&quot;</span>, id), <span class="dt">class =</span> <span class="st">&quot;boxxy-title&quot;</span>)</span>
<span id="cb329-12"><a href="custom-outputs.html#cb329-12"></a>  )</span>
<span id="cb329-13"><a href="custom-outputs.html#cb329-13"></a></span>
<span id="cb329-14"><a href="custom-outputs.html#cb329-14"></a>  path &lt;-<span class="st"> </span><span class="kw">normalizePath</span>(<span class="st">&quot;assets&quot;</span>)</span>
<span id="cb329-15"><a href="custom-outputs.html#cb329-15"></a></span>
<span id="cb329-16"><a href="custom-outputs.html#cb329-16"></a>  deps &lt;-<span class="st"> </span><span class="kw">list</span>(</span>
<span id="cb329-17"><a href="custom-outputs.html#cb329-17"></a>    htmltools<span class="op">::</span><span class="kw">htmlDependency</span>(</span>
<span id="cb329-18"><a href="custom-outputs.html#cb329-18"></a>      <span class="dt">name =</span> <span class="st">&quot;boxxy&quot;</span>,</span>
<span id="cb329-19"><a href="custom-outputs.html#cb329-19"></a>      <span class="dt">version =</span> <span class="st">&quot;1.0.0&quot;</span>,</span>
<span id="cb329-20"><a href="custom-outputs.html#cb329-20"></a>      <span class="dt">src =</span> <span class="kw">c</span>(<span class="dt">file =</span> path),</span>
<span id="cb329-21"><a href="custom-outputs.html#cb329-21"></a>      <span class="dt">script =</span> <span class="kw">c</span>(<span class="st">&quot;countup.js&quot;</span>, <span class="st">&quot;binding.js&quot;</span>),</span>
<span id="cb329-22"><a href="custom-outputs.html#cb329-22"></a>      <span class="dt">stylesheet =</span> <span class="st">&quot;styles.css&quot;</span></span>
<span id="cb329-23"><a href="custom-outputs.html#cb329-23"></a>    )</span>
<span id="cb329-24"><a href="custom-outputs.html#cb329-24"></a>  )</span>
<span id="cb329-25"><a href="custom-outputs.html#cb329-25"></a></span>
<span id="cb329-26"><a href="custom-outputs.html#cb329-26"></a>  htmltools<span class="op">::</span><span class="kw">attachDependencies</span>(el, deps)</span>
<span id="cb329-27"><a href="custom-outputs.html#cb329-27"></a>}</span>
<span id="cb329-28"><a href="custom-outputs.html#cb329-28"></a></span>
<span id="cb329-29"><a href="custom-outputs.html#cb329-29"></a>renderBoxxy &lt;-<span class="st"> </span><span class="cf">function</span>(expr, <span class="dt">env =</span> <span class="kw">parent.frame</span>(), </span>
<span id="cb329-30"><a href="custom-outputs.html#cb329-30"></a>  <span class="dt">quoted =</span> <span class="ot">FALSE</span>) {</span>
<span id="cb329-31"><a href="custom-outputs.html#cb329-31"></a>  <span class="co"># Convert the expression + environment into a function</span></span>
<span id="cb329-32"><a href="custom-outputs.html#cb329-32"></a>  func &lt;-<span class="st"> </span>shiny<span class="op">::</span><span class="kw">exprToFunction</span>(expr, env, quoted)</span>
<span id="cb329-33"><a href="custom-outputs.html#cb329-33"></a></span>
<span id="cb329-34"><a href="custom-outputs.html#cb329-34"></a>  <span class="cf">function</span>(){</span>
<span id="cb329-35"><a href="custom-outputs.html#cb329-35"></a>    <span class="kw">func</span>()</span>
<span id="cb329-36"><a href="custom-outputs.html#cb329-36"></a>  }</span>
<span id="cb329-37"><a href="custom-outputs.html#cb329-37"></a>}</span>
<span id="cb329-38"><a href="custom-outputs.html#cb329-38"></a></span>
<span id="cb329-39"><a href="custom-outputs.html#cb329-39"></a>ui &lt;-<span class="st"> </span><span class="kw">fluidPage</span>(</span>
<span id="cb329-40"><a href="custom-outputs.html#cb329-40"></a>  <span class="kw">h2</span>(<span class="st">&quot;Custom outputs&quot;</span>),</span>
<span id="cb329-41"><a href="custom-outputs.html#cb329-41"></a>  <span class="kw">fluidRow</span>(</span>
<span id="cb329-42"><a href="custom-outputs.html#cb329-42"></a>    <span class="kw">column</span>(</span>
<span id="cb329-43"><a href="custom-outputs.html#cb329-43"></a>      <span class="dv">3</span>, <span class="kw">boxxyOutput</span>(<span class="st">&quot;countries&quot;</span>)</span>
<span id="cb329-44"><a href="custom-outputs.html#cb329-44"></a>    ),</span>
<span id="cb329-45"><a href="custom-outputs.html#cb329-45"></a>    <span class="kw">column</span>(</span>
<span id="cb329-46"><a href="custom-outputs.html#cb329-46"></a>      <span class="dv">3</span>, <span class="kw">boxxyOutput</span>(<span class="st">&quot;employees&quot;</span>)</span>
<span id="cb329-47"><a href="custom-outputs.html#cb329-47"></a>    ),</span>
<span id="cb329-48"><a href="custom-outputs.html#cb329-48"></a>    <span class="kw">column</span>(</span>
<span id="cb329-49"><a href="custom-outputs.html#cb329-49"></a>      <span class="dv">3</span>, <span class="kw">boxxyOutput</span>(<span class="st">&quot;customers&quot;</span>)</span>
<span id="cb329-50"><a href="custom-outputs.html#cb329-50"></a>    ),</span>
<span id="cb329-51"><a href="custom-outputs.html#cb329-51"></a>    <span class="kw">column</span>(</span>
<span id="cb329-52"><a href="custom-outputs.html#cb329-52"></a>      <span class="dv">3</span>, <span class="kw">boxxyOutput</span>(<span class="st">&quot;subs&quot;</span>)</span>
<span id="cb329-53"><a href="custom-outputs.html#cb329-53"></a>    )</span>
<span id="cb329-54"><a href="custom-outputs.html#cb329-54"></a>  )</span>
<span id="cb329-55"><a href="custom-outputs.html#cb329-55"></a>)</span>
<span id="cb329-56"><a href="custom-outputs.html#cb329-56"></a></span>
<span id="cb329-57"><a href="custom-outputs.html#cb329-57"></a>server &lt;-<span class="st"> </span><span class="cf">function</span>(input, output){</span>
<span id="cb329-58"><a href="custom-outputs.html#cb329-58"></a>  output<span class="op">$</span>countries &lt;-<span class="st"> </span><span class="kw">renderBoxxy</span>({</span>
<span id="cb329-59"><a href="custom-outputs.html#cb329-59"></a>    <span class="kw">boxxy</span>(<span class="st">&quot;Countries&quot;</span>, <span class="dv">95</span>, <span class="dt">color =</span> <span class="st">&quot;#ef476f&quot;</span>)</span>
<span id="cb329-60"><a href="custom-outputs.html#cb329-60"></a>  })</span>
<span id="cb329-61"><a href="custom-outputs.html#cb329-61"></a></span>
<span id="cb329-62"><a href="custom-outputs.html#cb329-62"></a>  output<span class="op">$</span>employees &lt;-<span class="st"> </span><span class="kw">renderBoxxy</span>({</span>
<span id="cb329-63"><a href="custom-outputs.html#cb329-63"></a>    <span class="kw">boxxy</span>(<span class="st">&quot;Thing&quot;</span>, <span class="dv">650</span>, <span class="dt">color =</span> <span class="st">&quot;#06d6a0&quot;</span>)</span>
<span id="cb329-64"><a href="custom-outputs.html#cb329-64"></a>  })</span>
<span id="cb329-65"><a href="custom-outputs.html#cb329-65"></a></span>
<span id="cb329-66"><a href="custom-outputs.html#cb329-66"></a>  output<span class="op">$</span>customers &lt;-<span class="st"> </span><span class="kw">renderBoxxy</span>({</span>
<span id="cb329-67"><a href="custom-outputs.html#cb329-67"></a>    <span class="kw">boxxy</span>(<span class="st">&quot;Customers&quot;</span>, <span class="dv">13592</span>, <span class="dt">color =</span> <span class="st">&quot;#118ab2&quot;</span>)</span>
<span id="cb329-68"><a href="custom-outputs.html#cb329-68"></a>  })</span>
<span id="cb329-69"><a href="custom-outputs.html#cb329-69"></a></span>
<span id="cb329-70"><a href="custom-outputs.html#cb329-70"></a>  output<span class="op">$</span>subs &lt;-<span class="st"> </span><span class="kw">renderBoxxy</span>({</span>
<span id="cb329-71"><a href="custom-outputs.html#cb329-71"></a>    <span class="kw">boxxy</span>(<span class="st">&quot;Subscriptions&quot;</span>, <span class="dv">16719</span>, <span class="dt">color =</span> <span class="st">&quot;#ffd166&quot;</span>)</span>
<span id="cb329-72"><a href="custom-outputs.html#cb329-72"></a>  })</span>
<span id="cb329-73"><a href="custom-outputs.html#cb329-73"></a>}</span>
<span id="cb329-74"><a href="custom-outputs.html#cb329-74"></a></span>
<span id="cb329-75"><a href="custom-outputs.html#cb329-75"></a><span class="kw">shinyApp</span>(ui, server)</span></code></pre></div>
<div class="figure">
<img src="images/custom-output-boxxy.png" alt="" />
<p class="caption">Shiny application with boxxy</p>
</div>
</div>
<div id="injecting-dependencies" class="section level2" number="15.8">
<h2><span class="header-section-number">15.8</span> Injecting Dependencies</h2>
<p>We could consider making the animation of the value rendered with <code>boxxy</code> optional, some users may not want to use it. You might already imagine how a new argument and a few if statements could very easily do the job, but how would one handle the dependency? Surely if users do not want to make use of the animation the CountUp.js dependency should also be excluded so as to keep the output as light as possible.</p>
<p>The dependency is currently attached in the <code>boxxyOutput</code> function which does not take any argument, it could but it would make for rather messy and confusing interface as whatever additional argument that indicates whether the numbers should be animated would have be specified twice, once in the <code>boxxyOutput</code> function so it does not import the dependency as well as in the <code>boxxy</code> function in order to serialise that parameter so the JavaScript binding does not run the animation function.</p>
<div class="sourceCode" id="cb330"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb330-1"><a href="custom-outputs.html#cb330-1"></a><span class="co"># pseudo code</span></span>
<span id="cb330-2"><a href="custom-outputs.html#cb330-2"></a><span class="co"># do not do this</span></span>
<span id="cb330-3"><a href="custom-outputs.html#cb330-3"></a><span class="kw">library</span>(shiny)</span>
<span id="cb330-4"><a href="custom-outputs.html#cb330-4"></a></span>
<span id="cb330-5"><a href="custom-outputs.html#cb330-5"></a>ui &lt;-<span class="st"> </span><span class="kw">fluidPage</span>(</span>
<span id="cb330-6"><a href="custom-outputs.html#cb330-6"></a>  <span class="kw">boxxyOutput</span>(</span>
<span id="cb330-7"><a href="custom-outputs.html#cb330-7"></a>    <span class="st">&quot;countries&quot;</span>, </span>
<span id="cb330-8"><a href="custom-outputs.html#cb330-8"></a>    <span class="co"># do not import dependency</span></span>
<span id="cb330-9"><a href="custom-outputs.html#cb330-9"></a>    <span class="dt">animate =</span> <span class="ot">FALSE</span></span>
<span id="cb330-10"><a href="custom-outputs.html#cb330-10"></a>  )</span>
<span id="cb330-11"><a href="custom-outputs.html#cb330-11"></a>)</span>
<span id="cb330-12"><a href="custom-outputs.html#cb330-12"></a></span>
<span id="cb330-13"><a href="custom-outputs.html#cb330-13"></a>server &lt;-<span class="st"> </span><span class="cf">function</span>(input, output){</span>
<span id="cb330-14"><a href="custom-outputs.html#cb330-14"></a>  output<span class="op">$</span>countries &lt;-<span class="st"> </span><span class="kw">renderBoxxy</span>({</span>
<span id="cb330-15"><a href="custom-outputs.html#cb330-15"></a>    <span class="co"># do not animate the numbers</span></span>
<span id="cb330-16"><a href="custom-outputs.html#cb330-16"></a>    <span class="kw">boxxy</span>(<span class="st">&quot;Countries&quot;</span>, <span class="dv">95</span>, <span class="dt">animate =</span> <span class="ot">FALSE</span>)</span>
<span id="cb330-17"><a href="custom-outputs.html#cb330-17"></a>  })</span>
<span id="cb330-18"><a href="custom-outputs.html#cb330-18"></a>}</span>
<span id="cb330-19"><a href="custom-outputs.html#cb330-19"></a></span>
<span id="cb330-20"><a href="custom-outputs.html#cb330-20"></a><span class="kw">shinyApp</span>(ui, server)</span></code></pre></div>
<p>Thankfully there is a better way, combining htmltools and shiny to insert the dependency dynamically from JavaScript.</p>
<p>The <code>boxxy</code> function needs to take an additional argument <code>animate</code> which is passed to the output list. This will be used in the <code>render</code> function (and JavaScript binding) to dynamically render the dependency.</p>
<div class="sourceCode" id="cb331"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb331-1"><a href="custom-outputs.html#cb331-1"></a>boxxy &lt;-<span class="st"> </span><span class="cf">function</span>(title, value, <span class="dt">color =</span> <span class="st">&quot;black&quot;</span>, <span class="dt">aniamte =</span> <span class="ot">TRUE</span>){</span>
<span id="cb331-2"><a href="custom-outputs.html#cb331-2"></a>  <span class="kw">list</span>(<span class="dt">title =</span> title, <span class="dt">value =</span> value, <span class="dt">color =</span> color, <span class="dt">animate =</span> animate)</span>
<span id="cb331-3"><a href="custom-outputs.html#cb331-3"></a>}</span></code></pre></div>
<p>The <code>boxxyOutput</code> function can be slightly simplified, it currently attaches the <code>countup.js</code> dependency which needs to be removed.</p>
<div class="sourceCode" id="cb332"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb332-1"><a href="custom-outputs.html#cb332-1"></a>boxxyOutput &lt;-<span class="st"> </span><span class="cf">function</span>(id){</span>
<span id="cb332-2"><a href="custom-outputs.html#cb332-2"></a>  el &lt;-<span class="st"> </span>shiny<span class="op">::</span>tags<span class="op">$</span><span class="kw">div</span>(</span>
<span id="cb332-3"><a href="custom-outputs.html#cb332-3"></a>    <span class="dt">id =</span> id, <span class="dt">class =</span> <span class="st">&quot;boxxy&quot;</span>,</span>
<span id="cb332-4"><a href="custom-outputs.html#cb332-4"></a>    <span class="kw">h1</span>(<span class="dt">id =</span> <span class="kw">sprintf</span>(<span class="st">&quot;%s-boxxy-value&quot;</span>, id), <span class="dt">class =</span> <span class="st">&quot;boxxy-value&quot;</span>),</span>
<span id="cb332-5"><a href="custom-outputs.html#cb332-5"></a>    <span class="kw">p</span>(<span class="dt">id =</span> <span class="kw">sprintf</span>(<span class="st">&quot;%s-boxxy-title&quot;</span>, id), <span class="dt">class =</span> <span class="st">&quot;boxxy-title&quot;</span>)</span>
<span id="cb332-6"><a href="custom-outputs.html#cb332-6"></a>  )</span>
<span id="cb332-7"><a href="custom-outputs.html#cb332-7"></a></span>
<span id="cb332-8"><a href="custom-outputs.html#cb332-8"></a>  path &lt;-<span class="st"> </span><span class="kw">normalizePath</span>(<span class="st">&quot;assets&quot;</span>)</span>
<span id="cb332-9"><a href="custom-outputs.html#cb332-9"></a></span>
<span id="cb332-10"><a href="custom-outputs.html#cb332-10"></a>  <span class="co"># only attach binding.js</span></span>
<span id="cb332-11"><a href="custom-outputs.html#cb332-11"></a>  deps &lt;-<span class="st"> </span><span class="kw">list</span>(</span>
<span id="cb332-12"><a href="custom-outputs.html#cb332-12"></a>    htmltools<span class="op">::</span><span class="kw">htmlDependency</span>(</span>
<span id="cb332-13"><a href="custom-outputs.html#cb332-13"></a>      <span class="dt">name =</span> <span class="st">&quot;boxxy&quot;</span>,</span>
<span id="cb332-14"><a href="custom-outputs.html#cb332-14"></a>      <span class="dt">version =</span> <span class="st">&quot;1.0.0&quot;</span>,</span>
<span id="cb332-15"><a href="custom-outputs.html#cb332-15"></a>      <span class="dt">src =</span> <span class="kw">c</span>(<span class="dt">file =</span> path),</span>
<span id="cb332-16"><a href="custom-outputs.html#cb332-16"></a>      <span class="dt">script =</span> <span class="kw">c</span>(<span class="st">&quot;binding.js&quot;</span>),</span>
<span id="cb332-17"><a href="custom-outputs.html#cb332-17"></a>      <span class="dt">stylesheet =</span> <span class="st">&quot;styles.css&quot;</span></span>
<span id="cb332-18"><a href="custom-outputs.html#cb332-18"></a>    )</span>
<span id="cb332-19"><a href="custom-outputs.html#cb332-19"></a>  )</span>
<span id="cb332-20"><a href="custom-outputs.html#cb332-20"></a></span>
<span id="cb332-21"><a href="custom-outputs.html#cb332-21"></a>  htmltools<span class="op">::</span><span class="kw">attachDependencies</span>(el, deps)</span>
<span id="cb332-22"><a href="custom-outputs.html#cb332-22"></a>}</span></code></pre></div>
<p>The <code>renderBoxxy</code> function sees quite some modifications, while before it was technically only returning a function that itself returned the output of <code>boxxy</code> (<code>func() == boxxy()</code>). Here we want to capture the output of <code>boxxy</code> to check whether the <code>animate</code> element is <code>TRUE</code> and if so add the dependency.</p>
<div class="sourceCode" id="cb333"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb333-1"><a href="custom-outputs.html#cb333-1"></a>renderBoxxy &lt;-<span class="st"> </span><span class="cf">function</span>(expr, <span class="dt">env =</span> <span class="kw">parent.frame</span>(), </span>
<span id="cb333-2"><a href="custom-outputs.html#cb333-2"></a>  <span class="dt">quoted =</span> <span class="ot">FALSE</span>) {</span>
<span id="cb333-3"><a href="custom-outputs.html#cb333-3"></a>  <span class="co"># Convert the expression + environment into a function</span></span>
<span id="cb333-4"><a href="custom-outputs.html#cb333-4"></a>  func &lt;-<span class="st"> </span>shiny<span class="op">::</span><span class="kw">exprToFunction</span>(expr, env, quoted)</span>
<span id="cb333-5"><a href="custom-outputs.html#cb333-5"></a></span>
<span id="cb333-6"><a href="custom-outputs.html#cb333-6"></a>  <span class="cf">function</span>(){</span>
<span id="cb333-7"><a href="custom-outputs.html#cb333-7"></a>    val &lt;-<span class="st"> </span><span class="kw">func</span>()</span>
<span id="cb333-8"><a href="custom-outputs.html#cb333-8"></a></span>
<span id="cb333-9"><a href="custom-outputs.html#cb333-9"></a>    <span class="cf">if</span>(val<span class="op">$</span>animate){</span>
<span id="cb333-10"><a href="custom-outputs.html#cb333-10"></a>      <span class="co"># add dependency</span></span>
<span id="cb333-11"><a href="custom-outputs.html#cb333-11"></a>    }</span>
<span id="cb333-12"><a href="custom-outputs.html#cb333-12"></a></span>
<span id="cb333-13"><a href="custom-outputs.html#cb333-13"></a>    <span class="kw">return</span>(val)</span>
<span id="cb333-14"><a href="custom-outputs.html#cb333-14"></a>  }</span>
<span id="cb333-15"><a href="custom-outputs.html#cb333-15"></a>}</span></code></pre></div>
<p>Within the <code>if</code> statement the dependency can be created with the htmltools as done for the binding. Ensure the names of the dependencies are unique as shiny internally uses it to differentiate between them, if they bear the same name shiny assumes they are the same and will only render one of them.</p>
<div class="rmdnote">
<p>
Make sure dependencies bear different names or shiny thinks it’s the same and only renders one of them.
</p>
</div>
<p>The dependency generated with htmltools is then passed to the <code>shiny::createWebDependency</code> function which internally uses <code>shiny::addResourcePath</code> to serve the dependency. This is necessary here as, at this stage, the countup dependency is not actually rendered, below we merely add it to the list of options that serialised to JSON. Indeed this will actually be injected JavaScript-side, therefore the front-end needs to be able to access this file, hence it is served.</p>
<div class="sourceCode" id="cb334"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb334-1"><a href="custom-outputs.html#cb334-1"></a>renderBoxxy &lt;-<span class="st"> </span><span class="cf">function</span>(expr, <span class="dt">env =</span> <span class="kw">parent.frame</span>(), <span class="dt">quoted =</span> <span class="ot">FALSE</span>) {</span>
<span id="cb334-2"><a href="custom-outputs.html#cb334-2"></a>  <span class="co"># Convert the expression + environment into a function</span></span>
<span id="cb334-3"><a href="custom-outputs.html#cb334-3"></a>  func &lt;-<span class="st"> </span>shiny<span class="op">::</span><span class="kw">exprToFunction</span>(expr, env, quoted)</span>
<span id="cb334-4"><a href="custom-outputs.html#cb334-4"></a></span>
<span id="cb334-5"><a href="custom-outputs.html#cb334-5"></a>  <span class="cf">function</span>(){</span>
<span id="cb334-6"><a href="custom-outputs.html#cb334-6"></a>    <span class="co"># evaluate to output list</span></span>
<span id="cb334-7"><a href="custom-outputs.html#cb334-7"></a>    val &lt;-<span class="st"> </span><span class="kw">func</span>()</span>
<span id="cb334-8"><a href="custom-outputs.html#cb334-8"></a></span>
<span id="cb334-9"><a href="custom-outputs.html#cb334-9"></a>    <span class="co"># add dependency</span></span>
<span id="cb334-10"><a href="custom-outputs.html#cb334-10"></a>    <span class="cf">if</span>(val<span class="op">$</span>animate){</span>
<span id="cb334-11"><a href="custom-outputs.html#cb334-11"></a>      path &lt;-<span class="st"> </span><span class="kw">normalizePath</span>(<span class="st">&quot;assets&quot;</span>)</span>
<span id="cb334-12"><a href="custom-outputs.html#cb334-12"></a></span>
<span id="cb334-13"><a href="custom-outputs.html#cb334-13"></a>      deps &lt;-<span class="st"> </span>htmltools<span class="op">::</span><span class="kw">htmlDependency</span>(</span>
<span id="cb334-14"><a href="custom-outputs.html#cb334-14"></a>        <span class="dt">name =</span> <span class="st">&quot;countup&quot;</span>, <span class="co"># change name</span></span>
<span id="cb334-15"><a href="custom-outputs.html#cb334-15"></a>        <span class="dt">version =</span> <span class="st">&quot;1.8.2&quot;</span>,</span>
<span id="cb334-16"><a href="custom-outputs.html#cb334-16"></a>        <span class="dt">src =</span> <span class="kw">c</span>(<span class="dt">file =</span> path),</span>
<span id="cb334-17"><a href="custom-outputs.html#cb334-17"></a>        <span class="dt">script =</span> <span class="kw">c</span>(<span class="st">&quot;countup.js&quot;</span>) <span class="co"># only countup</span></span>
<span id="cb334-18"><a href="custom-outputs.html#cb334-18"></a>      )</span>
<span id="cb334-19"><a href="custom-outputs.html#cb334-19"></a></span>
<span id="cb334-20"><a href="custom-outputs.html#cb334-20"></a>      <span class="co"># serve dependency </span></span>
<span id="cb334-21"><a href="custom-outputs.html#cb334-21"></a>      val<span class="op">$</span>deps &lt;-<span class="st"> </span><span class="kw">list</span>(shiny<span class="op">::</span><span class="kw">createWebDependency</span>(deps))</span>
<span id="cb334-22"><a href="custom-outputs.html#cb334-22"></a>    }</span>
<span id="cb334-23"><a href="custom-outputs.html#cb334-23"></a></span>
<span id="cb334-24"><a href="custom-outputs.html#cb334-24"></a>    <span class="kw">return</span>(val)</span>
<span id="cb334-25"><a href="custom-outputs.html#cb334-25"></a>  }</span>
<span id="cb334-26"><a href="custom-outputs.html#cb334-26"></a>}</span></code></pre></div>
<p>Thus far the dependency is dynamically included in the R object that is serialised to JSON but it is not yet actually imported in the document, this happens in the JavaScript binding.</p>
<p>The first thing we ought to do is mirror the if statement that was created in the <code>renderBoxxy</code> function, if the numbers should be animated the function can use countup, if not it must insert the text with <code>insertText</code> just like it does for the <code>title</code>.</p>
<div class="sourceCode" id="cb335"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb335-1"><a href="custom-outputs.html#cb335-1"></a><span class="kw">var</span> boxxyBinding <span class="op">=</span> <span class="kw">new</span> Shiny<span class="op">.</span><span class="fu">OutputBinding</span>()<span class="op">;</span></span>
<span id="cb335-2"><a href="custom-outputs.html#cb335-2"></a></span>
<span id="cb335-3"><a href="custom-outputs.html#cb335-3"></a>$<span class="op">.</span><span class="fu">extend</span>(boxxyBinding<span class="op">,</span> {</span>
<span id="cb335-4"><a href="custom-outputs.html#cb335-4"></a>  <span class="dt">find</span><span class="op">:</span> <span class="kw">function</span>(scope) {</span>
<span id="cb335-5"><a href="custom-outputs.html#cb335-5"></a>    <span class="cf">return</span> $(scope)<span class="op">.</span><span class="fu">find</span>(<span class="st">&quot;.boxxy&quot;</span>)<span class="op">;</span></span>
<span id="cb335-6"><a href="custom-outputs.html#cb335-6"></a>  }<span class="op">,</span></span>
<span id="cb335-7"><a href="custom-outputs.html#cb335-7"></a>  <span class="dt">renderValue</span><span class="op">:</span> <span class="kw">function</span>(el<span class="op">,</span> data) {</span>
<span id="cb335-8"><a href="custom-outputs.html#cb335-8"></a></span>
<span id="cb335-9"><a href="custom-outputs.html#cb335-9"></a>    el<span class="op">.</span><span class="at">style</span><span class="op">.</span><span class="at">backgroundColor</span> <span class="op">=</span> data<span class="op">.</span><span class="at">color</span><span class="op">;</span></span>
<span id="cb335-10"><a href="custom-outputs.html#cb335-10"></a></span>
<span id="cb335-11"><a href="custom-outputs.html#cb335-11"></a>    <span class="cf">if</span>(data<span class="op">.</span><span class="at">animate</span>){</span>
<span id="cb335-12"><a href="custom-outputs.html#cb335-12"></a>      <span class="kw">var</span> counter <span class="op">=</span> <span class="kw">new</span> CountUp(el<span class="op">.</span><span class="at">id</span> <span class="op">+</span> <span class="st">&#39;-boxxy-value&#39;</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> data<span class="op">.</span><span class="at">value</span>)<span class="op">;</span></span>
<span id="cb335-13"><a href="custom-outputs.html#cb335-13"></a>      counter<span class="op">.</span><span class="fu">start</span>()<span class="op">;</span></span>
<span id="cb335-14"><a href="custom-outputs.html#cb335-14"></a>    } <span class="cf">else</span> {</span>
<span id="cb335-15"><a href="custom-outputs.html#cb335-15"></a>      <span class="bu">document</span><span class="op">.</span><span class="fu">getElementById</span>(el<span class="op">.</span><span class="at">id</span> <span class="op">+</span> <span class="st">&#39;-boxxy-value&#39;</span>)<span class="op">.</span><span class="at">innerText</span> <span class="op">=</span> data<span class="op">.</span><span class="at">value</span><span class="op">;</span></span>
<span id="cb335-16"><a href="custom-outputs.html#cb335-16"></a>    }</span>
<span id="cb335-17"><a href="custom-outputs.html#cb335-17"></a></span>
<span id="cb335-18"><a href="custom-outputs.html#cb335-18"></a>    <span class="bu">document</span><span class="op">.</span><span class="fu">getElementById</span>(el<span class="op">.</span><span class="at">id</span> <span class="op">+</span> <span class="st">&#39;-boxxy-title&#39;</span>)<span class="op">.</span><span class="at">innerText</span> <span class="op">=</span> data<span class="op">.</span><span class="at">title</span><span class="op">;</span></span>
<span id="cb335-19"><a href="custom-outputs.html#cb335-19"></a>  }</span>
<span id="cb335-20"><a href="custom-outputs.html#cb335-20"></a>})<span class="op">;</span></span>
<span id="cb335-21"><a href="custom-outputs.html#cb335-21"></a></span>
<span id="cb335-22"><a href="custom-outputs.html#cb335-22"></a>Shiny<span class="op">.</span><span class="at">outputBindings</span><span class="op">.</span><span class="fu">register</span>(boxxyBinding<span class="op">,</span> <span class="st">&quot;john.boxxy&quot;</span>)<span class="op">;</span></span></code></pre></div>
<p>Finally, we can render the dependency, the JavaScript method aptly named <code>renderDependencies</code> will do just that from the list of dependency created in <code>renderBoxxy</code>.</p>
<div class="sourceCode" id="cb336"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb336-1"><a href="custom-outputs.html#cb336-1"></a><span class="kw">var</span> boxxyBinding <span class="op">=</span> <span class="kw">new</span> Shiny<span class="op">.</span><span class="fu">OutputBinding</span>()<span class="op">;</span></span>
<span id="cb336-2"><a href="custom-outputs.html#cb336-2"></a></span>
<span id="cb336-3"><a href="custom-outputs.html#cb336-3"></a>$<span class="op">.</span><span class="fu">extend</span>(boxxyBinding<span class="op">,</span> {</span>
<span id="cb336-4"><a href="custom-outputs.html#cb336-4"></a>  <span class="dt">find</span><span class="op">:</span> <span class="kw">function</span>(scope) {</span>
<span id="cb336-5"><a href="custom-outputs.html#cb336-5"></a>    <span class="cf">return</span> $(scope)<span class="op">.</span><span class="fu">find</span>(<span class="st">&quot;.boxxy&quot;</span>)<span class="op">;</span></span>
<span id="cb336-6"><a href="custom-outputs.html#cb336-6"></a>  }<span class="op">,</span></span>
<span id="cb336-7"><a href="custom-outputs.html#cb336-7"></a>  <span class="dt">renderValue</span><span class="op">:</span> <span class="kw">function</span>(el<span class="op">,</span> data) {</span>
<span id="cb336-8"><a href="custom-outputs.html#cb336-8"></a></span>
<span id="cb336-9"><a href="custom-outputs.html#cb336-9"></a>    el<span class="op">.</span><span class="at">style</span><span class="op">.</span><span class="at">backgroundColor</span> <span class="op">=</span> data<span class="op">.</span><span class="at">color</span><span class="op">;</span></span>
<span id="cb336-10"><a href="custom-outputs.html#cb336-10"></a></span>
<span id="cb336-11"><a href="custom-outputs.html#cb336-11"></a>    <span class="cf">if</span>(data<span class="op">.</span><span class="at">animate</span>){</span>
<span id="cb336-12"><a href="custom-outputs.html#cb336-12"></a>      Shiny<span class="op">.</span><span class="fu">renderDependencies</span>(data<span class="op">.</span><span class="at">deps</span>)<span class="op">;</span> <span class="co">// render dependency</span></span>
<span id="cb336-13"><a href="custom-outputs.html#cb336-13"></a>      <span class="kw">var</span> counter <span class="op">=</span> <span class="kw">new</span> CountUp(el<span class="op">.</span><span class="at">id</span> <span class="op">+</span> <span class="st">&#39;-boxxy-value&#39;</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> data<span class="op">.</span><span class="at">value</span>)<span class="op">;</span></span>
<span id="cb336-14"><a href="custom-outputs.html#cb336-14"></a>      counter<span class="op">.</span><span class="fu">start</span>()<span class="op">;</span></span>
<span id="cb336-15"><a href="custom-outputs.html#cb336-15"></a>    } <span class="cf">else</span> {</span>
<span id="cb336-16"><a href="custom-outputs.html#cb336-16"></a>      <span class="bu">document</span><span class="op">.</span><span class="fu">getElementById</span>(el<span class="op">.</span><span class="at">id</span> <span class="op">+</span> <span class="st">&#39;-boxxy-value&#39;</span>)<span class="op">.</span><span class="at">innerText</span> <span class="op">=</span> data<span class="op">.</span><span class="at">value</span><span class="op">;</span></span>
<span id="cb336-17"><a href="custom-outputs.html#cb336-17"></a>    }</span>
<span id="cb336-18"><a href="custom-outputs.html#cb336-18"></a></span>
<span id="cb336-19"><a href="custom-outputs.html#cb336-19"></a>    <span class="bu">document</span><span class="op">.</span><span class="fu">getElementById</span>(el<span class="op">.</span><span class="at">id</span> <span class="op">+</span> <span class="st">&#39;-boxxy-title&#39;</span>)<span class="op">.</span><span class="at">innerText</span> <span class="op">=</span> data<span class="op">.</span><span class="at">title</span><span class="op">;</span></span>
<span id="cb336-20"><a href="custom-outputs.html#cb336-20"></a>  }</span>
<span id="cb336-21"><a href="custom-outputs.html#cb336-21"></a>})<span class="op">;</span></span>
<span id="cb336-22"><a href="custom-outputs.html#cb336-22"></a></span>
<span id="cb336-23"><a href="custom-outputs.html#cb336-23"></a>Shiny<span class="op">.</span><span class="at">outputBindings</span><span class="op">.</span><span class="fu">register</span>(boxxyBinding<span class="op">,</span> <span class="st">&quot;john.boxxy&quot;</span>)<span class="op">;</span></span></code></pre></div>
<p>With those changes made not only is the animation of numbers optional but if users decide to turn off the animation in all <code>boxxy</code> functions the <code>countup.js</code> file will not be included at all.</p>
<div class="sourceCode" id="cb337"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb337-1"><a href="custom-outputs.html#cb337-1"></a><span class="kw">library</span>(shiny)</span>
<span id="cb337-2"><a href="custom-outputs.html#cb337-2"></a></span>
<span id="cb337-3"><a href="custom-outputs.html#cb337-3"></a>ui &lt;-<span class="st"> </span><span class="kw">fluidPage</span>(</span>
<span id="cb337-4"><a href="custom-outputs.html#cb337-4"></a>  <span class="kw">h2</span>(<span class="st">&quot;Custom outputs&quot;</span>),</span>
<span id="cb337-5"><a href="custom-outputs.html#cb337-5"></a>  <span class="kw">fluidRow</span>(</span>
<span id="cb337-6"><a href="custom-outputs.html#cb337-6"></a>    <span class="kw">column</span>(</span>
<span id="cb337-7"><a href="custom-outputs.html#cb337-7"></a>      <span class="dv">3</span>, <span class="kw">boxxyOutput</span>(<span class="st">&quot;countries&quot;</span>)</span>
<span id="cb337-8"><a href="custom-outputs.html#cb337-8"></a>    ),</span>
<span id="cb337-9"><a href="custom-outputs.html#cb337-9"></a>    <span class="kw">column</span>(</span>
<span id="cb337-10"><a href="custom-outputs.html#cb337-10"></a>      <span class="dv">3</span>, <span class="kw">boxxyOutput</span>(<span class="st">&quot;employees&quot;</span>)</span>
<span id="cb337-11"><a href="custom-outputs.html#cb337-11"></a>    )</span>
<span id="cb337-12"><a href="custom-outputs.html#cb337-12"></a>  )</span>
<span id="cb337-13"><a href="custom-outputs.html#cb337-13"></a>)</span>
<span id="cb337-14"><a href="custom-outputs.html#cb337-14"></a></span>
<span id="cb337-15"><a href="custom-outputs.html#cb337-15"></a>server &lt;-<span class="st"> </span><span class="cf">function</span>(input, output){</span>
<span id="cb337-16"><a href="custom-outputs.html#cb337-16"></a>  output<span class="op">$</span>countries &lt;-<span class="st"> </span><span class="kw">renderBoxxy</span>({</span>
<span id="cb337-17"><a href="custom-outputs.html#cb337-17"></a>    <span class="kw">boxxy</span>(<span class="st">&quot;Countries&quot;</span>, <span class="dv">176</span>, <span class="dt">animate =</span> <span class="ot">FALSE</span>)</span>
<span id="cb337-18"><a href="custom-outputs.html#cb337-18"></a>  })</span>
<span id="cb337-19"><a href="custom-outputs.html#cb337-19"></a></span>
<span id="cb337-20"><a href="custom-outputs.html#cb337-20"></a>  output<span class="op">$</span>employees &lt;-<span class="st"> </span><span class="kw">renderBoxxy</span>({</span>
<span id="cb337-21"><a href="custom-outputs.html#cb337-21"></a>    <span class="kw">boxxy</span>(<span class="st">&quot;Thing&quot;</span>, <span class="dv">67</span>, <span class="dt">animate =</span> <span class="ot">FALSE</span>)</span>
<span id="cb337-22"><a href="custom-outputs.html#cb337-22"></a>  })</span>
<span id="cb337-23"><a href="custom-outputs.html#cb337-23"></a>}</span>
<span id="cb337-24"><a href="custom-outputs.html#cb337-24"></a></span>
<span id="cb337-25"><a href="custom-outputs.html#cb337-25"></a><span class="kw">shinyApp</span>(ui, server)</span></code></pre></div>
</div>
<div id="preprocessing-custom-outputs" class="section level2" number="15.9">
<h2><span class="header-section-number">15.9</span> Preprocessing Custom Outputs</h2>
<p>One aspect that this example did not explore truly explore thus far is the idea that the function <code>boxxy</code> should preprocess the input more in order to be truly justify. Currently <code>boxxy</code> only wraps the arguments in a <code>list</code>, therefore the code below works too.</p>
<div class="sourceCode" id="cb338"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb338-1"><a href="custom-outputs.html#cb338-1"></a><span class="co"># works too</span></span>
<span id="cb338-2"><a href="custom-outputs.html#cb338-2"></a>output<span class="op">$</span>theId &lt;-<span class="st"> </span><span class="kw">renderBoxxy</span>({</span>
<span id="cb338-3"><a href="custom-outputs.html#cb338-3"></a>  <span class="kw">list</span>(<span class="dt">title =</span> <span class="st">&quot;The Title&quot;</span>, <span class="dt">value =</span> <span class="dv">123</span>, <span class="dt">color =</span> <span class="st">&quot;blue&quot;</span>, <span class="dt">animate =</span> <span class="ot">TRUE</span>)</span>
<span id="cb338-4"><a href="custom-outputs.html#cb338-4"></a>})</span></code></pre></div>
<p>One the things <code>boxxy</code> could do is preprocess the input, below the function takes the sum of <code>value</code> to one pass a vector of any length and changes the default <code>color</code> argument to <code>NULL</code> so it is made dynamic based on the total <code>value</code>.</p>
<div class="sourceCode" id="cb339"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb339-1"><a href="custom-outputs.html#cb339-1"></a>boxxy &lt;-<span class="st"> </span><span class="cf">function</span>(title, value, <span class="dt">color =</span> <span class="ot">NULL</span>, <span class="dt">animate =</span> <span class="ot">TRUE</span>){</span>
<span id="cb339-2"><a href="custom-outputs.html#cb339-2"></a></span>
<span id="cb339-3"><a href="custom-outputs.html#cb339-3"></a>  <span class="co"># sum the vector</span></span>
<span id="cb339-4"><a href="custom-outputs.html#cb339-4"></a>  value &lt;-<span class="st"> </span><span class="kw">sum</span>(value)</span>
<span id="cb339-5"><a href="custom-outputs.html#cb339-5"></a></span>
<span id="cb339-6"><a href="custom-outputs.html#cb339-6"></a>  <span class="co"># dynamic color</span></span>
<span id="cb339-7"><a href="custom-outputs.html#cb339-7"></a>  <span class="cf">if</span>(<span class="kw">is.null</span>(color))</span>
<span id="cb339-8"><a href="custom-outputs.html#cb339-8"></a>    <span class="cf">if</span>(value <span class="op">&gt;</span><span class="st"> </span><span class="dv">100</span>)</span>
<span id="cb339-9"><a href="custom-outputs.html#cb339-9"></a>      color &lt;-<span class="st"> &quot;#ef476f&quot;</span></span>
<span id="cb339-10"><a href="custom-outputs.html#cb339-10"></a>    <span class="cf">else</span></span>
<span id="cb339-11"><a href="custom-outputs.html#cb339-11"></a>      color &lt;-<span class="st"> &quot;#06d6a0&quot;</span></span>
<span id="cb339-12"><a href="custom-outputs.html#cb339-12"></a></span>
<span id="cb339-13"><a href="custom-outputs.html#cb339-13"></a>  <span class="kw">list</span>(<span class="dt">title =</span> title, <span class="dt">value =</span> value, <span class="dt">color =</span> color, <span class="dt">animate =</span> animate)</span>
<span id="cb339-14"><a href="custom-outputs.html#cb339-14"></a>}</span></code></pre></div>
<p>This means boxxy could be used like so: <code>boxxy("Total", c(1,6,9))</code>.</p>

</div>
</div>
<h3>References</h3>
<div id="refs" class="references">
<div id="ref-R-shinydashboard">
<p>Chang, Winston, and Barbara Borges Ribeiro. 2018. <em>Shinydashboard: Create Dashboards with ’Shiny’</em>. <a href="https://CRAN.R-project.org/package=shinydashboard">https://CRAN.R-project.org/package=shinydashboard</a>.</p>
</div>
</div>
            </section>

          </div>
        </div>
      </div>
<a href="tips-tricks.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
<a href="custom-inputs.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a>
    </div>
  </div>
<script src="libs/gitbook/js/app.min.js"></script>
<script src="libs/gitbook/js/lunr.js"></script>
<script src="libs/gitbook/js/clipboard.min.js"></script>
<script src="libs/gitbook/js/plugin-search.js"></script>
<script src="libs/gitbook/js/plugin-sharing.js"></script>
<script src="libs/gitbook/js/plugin-fontsettings.js"></script>
<script src="libs/gitbook/js/plugin-bookdown.js"></script>
<script src="libs/gitbook/js/jquery.highlight.js"></script>
<script src="libs/gitbook/js/plugin-clipboard.js"></script>
<script>
gitbook.require(["gitbook"], function(gitbook) {
gitbook.start({
"sharing": {
"github": true,
"facebook": false,
"twitter": false,
"linkedin": false,
"weibo": false,
"instapaper": false,
"vk": false,
"all": {}
},
"fontsettings": {
"theme": "white",
"family": "sans",
"size": 2
},
"edit": {
"link": "https://github.com/JohnCoene/javascript-for-r/edit/master/4-15-shiny-output.Rmd",
"text": "Edit"
},
"history": {
"link": null,
"text": null
},
"view": {
"link": null,
"text": null
},
"download": {},
"toc": {
"collapse": "section"
}
});
});
</script>

</body>

</html>
